Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А если серьезнее — я как-то с трудом себе представляю автозавод, например, руководство которого бы заявило — да, наша машина ездит со скоростью в 5 раз ниже, чем у конкурентов, но зато посмотрите, как легко нашим конструкторам было ее разработать и нашим рабочим собирать! И изменить ее легко, правда, не исключено, что она будет после этого иметь скорость в 10 раз ниже.
Но, тем не менее, скорость большинства автомобилей как раз настолько меньше максимальной достигнутой.
Особого спроса на сверхзвуковые автомобили нет. Выдающееся инженерное достижение любой ценой — это, безусловно, впечатлающе, но практичные решения привлекают людей больше.
... << RSDN@Home 1.2.0 alpha 4 rev. 1228>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Здравствуйте, Пельмешко, Вы писали:
П>Не знаю :) Чисто академический интерес, наверное, или любовь к декларативности :) П>Разве это не прекрасно? :shuffle: П>
Здравствуйте, Пельмешко, Вы писали:
П>Здравствуйте, Pavel Dvorkin, Вы писали:
G>>>или еще как-то скомбинировать результирующую последовательность с другими операциями.
PD>>Кто мешает ?
П>удобство То, что Вы напишете императивными циклами с прыжками
Прыжками — это goto ? С фортрановских времен не писал. Как-нибудь обойдусь.
>и несколькими уровнями вложенности будет намного сложнее читать и анализировать, чем пару декларативных строчек на linq \ любом ФЯ.
Сложнее читать — верно. Кому читать — человеку ? Да.
Сложнее анализировать — верно. Кому анализировать — человеку ? Да.
А работать-то программа должна не в мозгу человека, а в машине!
Кто же за бедную машину-то заступится ? Жалко ее. Столько бессмысленной работы делать!
А если серьезнее — я как-то с трудом себе представляю автозавод, например, руководство которого бы заявило — да, наша машина ездит со скоростью в 5 раз ниже, чем у конкурентов, но зато посмотрите, как легко нашим конструкторам было ее разработать и нашим рабочим собирать! И изменить ее легко, правда, не исключено, что она будет после этого иметь скорость в 10 раз ниже.
И коли в ИТ такой подход не вызывает противодействия — значит, что-то неладно в Датском Королевстве.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> И мы так и не узнаем, что могли бы иметь многие программы. Потому что эти программы никогда не будут написаны. А не будут потому, что оценка их быстродействия, основанная на текущем состоянии, даст, что для них надо 20 ГГц, а где их взять ? А в реальности им надо не 20, а только 3, и вполне можно было бы их сделать...
Как где взять? Поставить 8 ядер.
А к тому времени, когда ты напишешь эти программы, используя такие низкоуровневые средства, как циклы, и пофиксишь баги до приемлемого уровня, эти программы уже будут никому не нужны.
Вот куда действительно было бы полезно вложить силы — так это в создание высокооптимизирующих компиляторов. Кстати, код, написанный в декларативном стиле, гораздо лучше поддаётся анализу и оптимизации.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А если честнее потому, что это более соответствует тому, что генерируется LinQ — то мне до этого и дела нет. Задача поставлена ясно
Вы меня простите ради Бога, каюсь, в этом я ошибался конечно, почему то решил, что топикстартер привёл ряд вида 1,2,3...n в качестве примера, я именно ожидал что у него там SomeHardFunction(i), думал задача реальная, откуда-то ряд берётся... А надо было лишь получше прочитать, извините...
PD>Не удивительно. Удивительно другое — несмотря на это, находятся желающие его использовать в ситуации, когда простой императивный код занимает 3 строчки и работает в 6 раз быстрее. Вот скажи на милость (или пусть топикстартер скажет) — зачем он ему в этой задаче понадобился ???
Не знаю Чисто академический интерес, наверное, или любовь к декларативности
Разве это не прекрасно?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Объясняю популярно — давай время работы программы, а не машинистки.
У вас в конторе код набирают машинистки под диктовку?
PD>Меня не интересует простота восприятия.
Павел, вы, видимо, не работаете в коллективе?
PD>Сколько времени в мсек этот код работает? Запусти и приведи результат.
Я по-умолчанию предполагаю, что наиболее простой для восприятия код с эквивалентной асимптотикой работает достаточно быстро — пока не доказано обратное. Когда будет доказано — и не в попугаях, а в профилировщике (т.е. с учётом частоты выполнения участка кода) — только тогда и надо думать об оптимизации.
Наш внештатный К.О. с мест докладывает, что всё это уже говорилось на RSDN сотни раз.
Здравствуйте, Аноним, Вы писали:
П>>let sums = { 0 .. n } |> Seq.scan (+) 0 П>>[/ocaml]
А>расшифруйте пожалуйста эту запись (выделенная часть совсем непонятна)
Это F#. Значит вот что: берем функцию Seq.scan, применяем ее к 2 аргументам: к функции, складывающей 2 числа, и к числу 0. Получается функция, принимающая один аргумент. И ей мы скармливаем (|>) последовательность чисел от 0 до n.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А если честнее потому, что это более соответствует тому, что генерируется LinQ — то мне до этого и дела нет. Задача поставлена ясно
PD>//////////////////////////////////////////////////// PD>Есит ряд:
PD>1, 2, 3, 4, ..... n
PD>Надо через LINQ получить из него ряд частичных сумм:
PD>1, 3, 6, 10, ... m
PD>////////////////////////////////////////////////////
PD>Вот я и сделал этот ряд частичных сумм, и пусть мне кто-то докажет обратное.
См. выделенное
Luck in life always exists in the form of an abstract class that cannot be instantiated directly and needs to be inherited by hard work and dedication.
Вся демагогия отправлена в Recycled Bin. Единственное, что могло бы убедить меня продолжить дискуссию — это конкретные данные по времени. Их нет. Поэтому прекращаю.
Здравствуйте, Пельмешко, Вы писали:
П>Всё равно никто ничего никому не докажет, каждый останется при своих любимых игрушках, будь то императивные циклы или фвп...
Ну вот на моих типичных задачах, где size порядка 5000, то такой подсчёт времени выдал «00:00:00» и «00:00:00» соответственно. Что вполне соответствует закономерности, которую «требуется получить», ведь 0 действительно равен 5·0.
Здравствуйте, Northrop, Вы писали:
N>Есит ряд:
N>1, 2, 3, 4, ..... n
N>Надо через LINQ получить из него ряд частичных сумм:
N>1, 3, 6, 10, ... m
N>Как это сделать?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var m = 50;
var ll = Enumerable.Range(1, 100);
Func<int, bool> ff = (i) => (i % 3 == 0 && i < m) ? true : false;
var sum = ll.Where(x => ff(x)).Sum();
Console.WriteLine(sum);
}
}
}
Re: LINQ - Как получить частичные суммы ряда?
От:
Аноним
Дата:
07.09.09 03:52
Оценка:
Здравствуйте, Northrop, Вы писали:
N>Есит ряд:
N>1, 2, 3, 4, ..... n
N>Надо через LINQ получить из него ряд частичных сумм:
N>1, 3, 6, 10, ... m
N>Как это сделать?
самый красивый вариант
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var sum = 0;
var ss = Enumerable.Range(1, 100).Select(x => { sum += x; return sum; });
ss.ToList().ForEach(x => Console.WriteLine(x));
}
}
}
Здравствуйте, Аноним, Вы писали:
А>самый красивый вариант
Да уж...
static void Main(string[] args)
{
// исходный код, только вывод убралint size = 50000000;
var sum = 0;
DateTime Start = DateTime.Now;
var ss = Enumerable.Range(1, size).Select(x => { sum += x; return sum; });
List<int> s = ss.ToList();
DateTime End = DateTime.Now;
TimeSpan time = End - Start;
Console.WriteLine(time);
// а теперь попробуем по-простому
Start = DateTime.Now;
int[] array = new int[size];
array[0] = 0;
for (int i = 1; i < size; i++)
array[i] = array[i - 1] + i;
End = DateTime.Now;
time = End - Start;
Console.WriteLine(time);
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Да уж...
[ поскипано ]
PD>Почти 6-кратный проигрыш!
Некошерно как-то мерить DateTime'ом, да и не особо эквивалентный код
Не забывайте, что от ленивости может быть бенефит, а так же может нельзя переиспользовать массив исходных данных (массив ли там вообще на входе?), смотря какая задача там у топикстартера
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApp
{
public static class Program
{
public static string Test(
int iterCount, params Func<string>[] tests)
{
if (tests == null)
throw new ArgumentNullException("tests");
var thread = Thread.CurrentThread;
var oldPriority = thread.Priority;
var timer = new Stopwatch();
var buf = new StringBuilder();
try
{
// прогревочный круг :Dforeach (var test in tests) test();
thread.Priority = ThreadPriority.Highest;
int n = 1;
foreach (var test in tests)
{
timer.Start();
string name = null;
for (int i=0; i < iterCount; i++) name = test();
timer.Stop();
buf.AppendFormat(
"Test #{0} {1,16}: {2} ({3} ms)\n", n++,
name, timer.Elapsed, timer.ElapsedMilliseconds);
timer.Reset();
}
}
finally { thread.Priority = oldPriority; }
return buf.ToString();
}
static void Main()
{
const int Size = 50000;
string result = Test(1000,
() => {
int sum = 0;
var ss = Enumerable.Range(1, Size)
.Select(x => { sum += x; return sum; }).ToList();
return"Linq";
},
() => {
var xx = Enumerable.Range(1, Size)
.Aggregate(new List<int> { 0 },
(l, x) => { l.Add(l[l.Count-1] + x); return l; });
return"Linq2";
},
() => {
var xx = new List<int>();
Enumerable.Range(1, Size).Aggregate(
(a, x) => { xx.Add(x); return a; });
return"Linq3";
},
() => {
int[] array = new int[Size];
for (int i = 1; i < array.Length; i++) // use length-based loop!
array[i] = array[i-1] + i;
return"Imperative";
},
() => {
int[] array = new int[Size],
scan = new int[Size];
for(int i = 0; i < array.Length; i++) array[i] = i;
int sum = 0;
for(int i = 0; i < scan.Length; i++)
{
sum += array[i];
scan[i] = sum;
}
return"Imper.(честнее)";
});
Console.WriteLine(result);
}
}
}
Test #1 Linq: 00:00:02.8320702 (2832 ms)
Test #2 Linq2: 00:00:02.2512573 (2251 ms)
Test #3 Linq3: 00:00:01.7357650 (1735 ms)
Test #4 Imperative: 00:00:00.3250726 (325 ms)
Test #5 Imper.(честнее): 00:00:00.5843982 (584 ms)
Athlon X2 3800+
p.s. Раньше ради интереса гонял тесты, linq всегда проигрывал в 2-3 раза эквивалентному eager-коду на циклах.
Не удивительно, сколько там вызовов делегатов с замыканиями, интерфейсных вызовов IEnumerable<T> и т.п...
Простите, чушь в третьем случае написал, вот так правильно:
() => {
var xx = new List<int> { 0 };
Enumerable.Range(1, Size).Aggregate(
(a, x) => { int s = a+x; xx.Add(s); return s; });
return"Linq3";
},
Результата это не меняет, у меня даже меньше вышло, хотя это скорее всего из-за погрешности:
Test #1 Linq: 00:00:02.8420874 (2842 ms)
Test #2 Linq2: 00:00:02.2010004 (2201 ms)
Test #3 Linq3: 00:00:01.7111976 (1711 ms)
Test #4 Imperative: 00:00:00.3063548 (306 ms)
Test #5 Imper.(честнее): 00:00:00.5250748 (525 ms)
Кстати, третий случай быстрее потому что там не генерится скрытый класс для замыкания, target'ом делегата становится сам List<int> xx.
То есть доступ к нему в лямбде будет не this.xx.Add(), а просто this.Add()
Здравствуйте, Пельмешко, Вы писали:
П>Кстати, третий случай быстрее потому что там не генерится скрытый класс для замыкания, target'ом делегата становится сам List<int> xx. П>То есть доступ к нему в лямбде будет не this.xx.Add(), а просто this.Add()
А если ещё capacity подсказать списку, то выходит ещё интереснее
Test #3 Linq3: 00:00:01.3988305 (1398 ms)
Re[5]: LINQ - Как получить частичные суммы ряда?
От:
Аноним
Дата:
07.09.09 10:13
Оценка:
Здравствуйте, Пельмешко, Вы писали:
П>Здравствуйте, Пельмешко, Вы писали:
П>Простите, чушь в третьем случае написал, вот так правильно: П>
П> () => {
П> var xx = new List<int> { 0 };
П> Enumerable.Range(1, Size).Aggregate(
П> (a, x) => { int s = a+x; xx.Add(s); return s; });
П> return"Linq3";
П> },
П>
П>Результата это не меняет, у меня даже меньше вышло, хотя это скорее всего из-за погрешности: П>
П>Кстати, третий случай быстрее потому что там не генерится скрытый класс для замыкания, target'ом делегата становится сам List<int> xx. П>То есть доступ к нему в лямбде будет не this.xx.Add(), а просто this.Add()
а зачем List<int> юзать?
При тех значениях (десятые доли секунды) , что GetTickCount, что QueryPerfomanceCounter — один черт. Разрешение GetTickCount — 0.015 сек. Ну не в 6 раз, так в 5.95 раз
П> () => { П> int[] array = new int[Size], П> scan = new int[Size];
П> for(int i = 0; i < array.Length; i++) array[i] = i;
П> int sum = 0; П> for(int i = 0; i < scan.Length; i++) П> { П> sum += array[i]; П> scan[i] = sum; П> }
П> return "Imper.(честнее)";
Хм, а почему же честнее ? Завел ты непонятно зачем еще один массив, да еще со значениями array[i] = i. Не обижайся, но за такие массивы я школьникам втык делал. Ибо незачем такие массивы заводить. Я бы еще понял, если бы array[]= SomeHardFunction(i), тут еще можно подискутировать, вычислять ее каждый раз или предварительно просчитать и в массив. А array[i] = i — ИМХО безобразие.
А если честнее потому, что это более соответствует тому, что генерируется LinQ — то мне до этого и дела нет. Задача поставлена ясно
Вот я и сделал этот ряд частичных сумм, и пусть мне кто-то докажет обратное. И если при этом LinQ или кто-то еще должен соорудить какие-то еще массивы или иные контейнеры — меня это не касается. Я свое дело сделал и так.
П>Не удивительно, сколько там вызовов делегатов с замыканиями, интерфейсных вызовов IEnumerable<T> и т.п...
Не удивительно. Удивительно другое — несмотря на это, находятся желающие его использовать в ситуации, когда простой императивный код занимает 3 строчки и работает в 6 раз быстрее. Вот скажи на милость (или пусть топикстартер скажет) — зачем он ему в этой задаче понадобился ???
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Не удивительно. Удивительно другое — несмотря на это, находятся желающие его использовать в ситуации, когда простой императивный код занимает 3 строчки и работает в 6 раз быстрее. Вот скажи на милость (или пусть топикстартер скажет) — зачем он ему в этой задаче понадобился ???
Ну например ему может понадобится найти максимальную из четных сумм, которые меньше заданного числа...
или еще как-то скомбинировать результирующую последовательность с другими операциями.
Здравствуйте, gandjustas, Вы писали:
G>Ну например ему может понадобится найти максимальную из четных сумм, которые меньше заданного числа...
И что ? В том массиве, что я сделал, ее найти нельзя ? Кстати, если уж именно это надо — оборву цикл, как найду первую сумму, которая больше заданного, ибо дальше будет еще больше . И для этой задачи и массив-то совсем не нужен. Ни один. Суммируй в одну переменную пока сумма >= заданного не станет, и отмечай максимальную из четных.
G>или еще как-то скомбинировать результирующую последовательность с другими операциями.
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, Пельмешко, Вы писали:
П>>Не знаю Чисто академический интерес, наверное, или любовь к декларативности П>>Разве это не прекрасно? П>>
Здравствуйте, Pavel Dvorkin, Вы писали:
G>>или еще как-то скомбинировать результирующую последовательность с другими операциями.
PD>Кто мешает ?
удобство То, что Вы напишете императивными циклами с прыжками и несколькими уровнями вложенности будет намного сложнее читать и анализировать, чем пару декларативных строчек на linq \ любом ФЯ.
array[0] = 0;
for (int i = 1; i < size; i++)
array[i] = array[i - 1] + i;
t ≈ 80 символов ∕ v символов/секунда
При том, что первый способ проще для восприятия, так как оперирует коллекциями, а не их элементами. (Это как в математике — инвариантная запись формулы предпочтительнее покоординатной-в-некотором-базисе.)
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Пельмешко, Вы писали:
П>>Разве это не прекрасно? П>>
П>>let sums = { 0 .. n } |> Seq.scan (+) 0
П>>
PD>Прекрасно, но при условии, что это работает на абстрактной машине
Ага, я прям смотрю на это и ужасаюсь:
+ виртуальный вызов на каждое сложение!
+ по два интерфейсных вызова на элемент (а они в .net ух медленные какие, там же практически двойная косвенность)!
+ на аккумулятор аж 4 байта выделяется!
+ статический вызов Seq.scan, аж с тремя аргументами!
+ генератор последовательности на куче создать надо, ужос...
Здравствуйте, Qbit86, Вы писали:
Q>Время работы зависит от скорости. Пусть скорость набора — v, тогда
<skipped>
Объясняю популярно — давай время работы программы, а не машинистки.
Q>При том, что первый способ проще для восприятия, так как оперирует коллекциями, а не их элементами. (Это как в математике — инвариантная запись формулы предпочтительнее покоординатной-в-некотором-базисе.)
Меня не интересует простота восприятия. Сколько времени в мсек этот код работает ? Запусти и приведи результат.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, gandjustas, Вы писали:
G>>Ну например ему может понадобится найти максимальную из четных сумм, которые меньше заданного числа...
PD>И что ? В том массиве, что я сделал, ее найти нельзя ? Кстати, если уж именно это надо — оборву цикл, как найду первую сумму, которая больше заданного, ибо дальше будет еще больше . И для этой задачи и массив-то совсем не нужен. Ни один. Суммируй в одну переменную пока сумма >= заданного не станет, и отмечай максимальную из четных.
именно этим код со scan и занимается
Только возможностей по композиции у него гораздо больше.
Тебе же придется переписывать большую часть кода при незначительном изменении условий.
G>>или еще как-то скомбинировать результирующую последовательность с другими операциями. PD>Кто мешает ?
Циклы мешают.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Пельмешко, Вы писали:
П>>удобство То, что Вы напишете императивными циклами с прыжками
PD>Прыжками — это goto ? С фортрановских времен не писал. Как-нибудь обойдусь.
Вы упомянули break, которым могли бы раньше выйти из цикла, а он и есть тот же самый прыжок.
ФВП тоже могут остановить цикл прохода по последовательности, тем же break, только это скрыто внутри них, а я не буду думать куда этот break перенесёт поток управления, я просто получу результат.
PD>Кто же за бедную машину-то заступится ? Жалко ее. Столько бессмысленной работы делать!
Это не бессмысленная работа, просто другой способ исполнять ту же работу, просто менее эффективный в силу архитектуры.
PD>И коли в ИТ такой подход не вызывает противодействия — значит, что-то неладно в Датском Королевстве.
Задачи становятся всё сложнее и сложнее, сложность кода возрастает и одними циклами просто уже не обойтись.
Да, самый низ лучше строить на императивных циклах, но задачи чуть выше гораздо удобнее описывать в терминах ФВП.
Здравствуйте, Пельмешко, Вы писали:
PD>>Прыжками — это goto ? С фортрановских времен не писал. Как-нибудь обойдусь.
П>Вы упомянули break, которым могли бы раньше выйти из цикла, а он и есть тот же самый прыжок. П>ФВП тоже могут остановить цикл прохода по последовательности, тем же break, только это скрыто внутри них, а я не буду думать куда этот break перенесёт поток управления, я просто получу результат.
Я не спорю, что это может быть понятнее, но какой ценой!
PD>>Кто же за бедную машину-то заступится ? Жалко ее. Столько бессмысленной работы делать!
П>Это не бессмысленная работа, просто другой способ исполнять ту же работу, просто менее эффективный в силу архитектуры.
А кому нужен автомобиль, который ездит в 5 раз медленее в силу архитектуры ?
PD>>И коли в ИТ такой подход не вызывает противодействия — значит, что-то неладно в Датском Королевстве.
П>Задачи становятся всё сложнее и сложнее, сложность кода возрастает и одними циклами просто уже не обойтись.
Ну не надо. Все эти "сложные задачи" (в том. что все становится сложнее и сложнее, не уверен, но не буду сейчас говорить) решаются императивными циклами и т.д. И вообще ИМХО еще не придумали задач, которые императивными языками вообще не решаются. Доказательство простое — исполняться будет в конечном счете ассемблерный код, а там ничего другого нет (подчеркиваю, доказательство, а не призыв писать на ассемблере). Так что обойтись в приницпе можно всегда. Хотя да, это может оказаться не очень простым и не очень понятным. Но в любом случае — если ты это не сделаешь, это сделают за тебя (LinQ или иная исполняющая система). И не лучшим образом, как видно даже из этого простейшего примера, что уж говорить о более сложных!
П>Да, самый низ лучше строить на императивных циклах, но задачи чуть выше гораздо удобнее описывать в терминах ФВП.
И все же — не слишком ли дорогой ценой? Вот топикстартер , если и впрямь использует этот красивый код, понизит быстродействие в 3-6 раз. Иными словами, это примерно то же самое (не придирайся к деталям), как если бы вместо машины на 3 Ггц он использовал машину на 1 ГГц, а то и на 500 Мгц. То есть отбросит нас на 2-5 лет назад. Во имя того, чтобы ему было проще это несчастное суммирование делать ? А потом это войдет в норму (ох, не вошло ли уже?), и все будут уверены, что такой код и должен с таким быстродействием работать. И мы так и не узнаем, что могли бы иметь многие программы. Потому что эти программы никогда не будут написаны. А не будут потому, что оценка их быстродействия, основанная на текущем состоянии, даст, что для них надо 20 ГГц, а где их взять ? А в реальности им надо не 20, а только 3, и вполне можно было бы их сделать...
На сегодня все, ухожу домой
With best regards
Pavel Dvorkin
Re[6]: LINQ - Как получить частичные суммы ряда?
От:
Аноним
Дата:
07.09.09 17:07
Оценка:
Здравствуйте, Пельмешко, Вы писали:
П>Разве это не прекрасно? П>
П>let sums = { 0 .. n } |> Seq.scan (+) 0
П>
расшифруйте пожалуйста эту запись (выделенная часть совсем непонятна)
Здравствуйте, nikov, Вы писали:
П>>>let sums = { 0 .. n } |> Seq.scan (+) 0 П>>>[/ocaml]
А>>расшифруйте пожалуйста эту запись (выделенная часть совсем непонятна)
N>Это F#. Значит вот что: берем функцию Seq.scan, применяем ее к 2 аргументам: к функции, складывающей 2 числа, и к числу 0. Получается функция, принимающая один аргумент. И ей мы скармливаем (|>) последовательность чисел от 0 до n.
Можно подробнее почитать в MSDN, например, начиная отсюда.
Здравствуйте, nikov, Вы писали:
PD>> И мы так и не узнаем, что могли бы иметь многие программы. Потому что эти программы никогда не будут написаны. А не будут потому, что оценка их быстродействия, основанная на текущем состоянии, даст, что для них надо 20 ГГц, а где их взять ? А в реальности им надо не 20, а только 3, и вполне можно было бы их сделать...
N>Как где взять? Поставить 8 ядер.
Так ведь если поставить 8 ядер, получится все равно то же самое, только на другом, более высоком уровне. Ты будешь их использовать как 3 GGz, а для того, чтобы использовать все 20, тебе понадобится 120 . Суть-то проста — используется 20% реальной мощности, независимо от того, чему она равна.
N>Вот куда действительно было бы полезно вложить силы — так это в создание высокооптимизирующих компиляторов. Кстати, код, написанный в декларативном стиле, гораздо лучше поддаётся анализу и оптимизации.
Здравствуйте, gandjustas, Вы писали:
PD>>И что ? В том массиве, что я сделал, ее найти нельзя ? Кстати, если уж именно это надо — оборву цикл, как найду первую сумму, которая больше заданного, ибо дальше будет еще больше . И для этой задачи и массив-то совсем не нужен. Ни один. Суммируй в одну переменную пока сумма >= заданного не станет, и отмечай максимальную из четных.
G>именно этим код со scan и занимается G>Только возможностей по композиции у него гораздо больше. G>Тебе же придется переписывать большую часть кода при незначительном изменении условий.
Придется.
G>>>или еще как-то скомбинировать результирующую последовательность с другими операциями. PD>>Кто мешает ? G>Циклы мешают.
Ты считаешь, что их реально нет в коде, сгенерированном LinQ ? Или это просто продолжение предыдущего — что мне придется многое переписывать ? Если второе — да, согласен, но я не согласен с тем, что ради того, чтобы сделать жизнь программиста легче, можно позволить себе 5-6 кратное замедление.
Ну а с тем, что это можно написать с циклами (да, сложнее) я думаю, спорить ты не будешь.
Здравствуйте, Qbit86, Вы писали:
Q>У вас в конторе код набирают машинистки под диктовку?
У Вас принято все слова понимать буквально ? Или надо расшифровать, что я имел в виду ?
PD>>Меня не интересует простота восприятия.
Q>Павел, вы, видимо, не работаете в коллективе?
Работаю. В сильно распределенном коллективе
PD>>Сколько времени в мсек этот код работает? Запусти и приведи результат.
Q>Я по-умолчанию предполагаю, что наиболее простой для восприятия код с эквивалентной асимптотикой работает достаточно быстро — пока не доказано обратное.
А я именно обратное и доказал, правда, не для твоего примера, а для LinQ. А что касается твоего примера — предполагай что хочешь, твое право, но пока ты не дашь доказательства твоего предположения (в секундах и миллисекундах), твое предположение ничего не стоит.
Может, хватит всяких прочих утверждений ? Приведи время работы!
>Когда будет доказано — и не в попугаях, а в профилировщике (т.е. с учётом частоты выполнения участка кода) — только тогда и надо думать об оптимизации.
В общем так. Все голословные утвреждения меня мало интересуют. Равно как и рассуждения о том, что надо и что не надо оптимизировать. Это другой вопрос. Либо приводи время работы своей программы, либо не стоит продолжать.
Q>Павел, современные машины в вашей защите не нуждаются, честно Чай не маленькие. Тем более в защите от ветряных мельниц.
Здравствуйте, Pavel Dvorkin, Вы писали:
Q>>У вас в конторе код набирают машинистки под диктовку?
PD>У Вас принято все слова понимать буквально ? Или надо расшифровать, что я имел в виду ?
Да, лучше расшифруйте. Я уж не знаю, что вы имели в виду проводя заведомо дырявую аналогию между машинисткой и разработчиком. В данном контексте я трактую слово «машинистка» как низкоквалифицированного работника, который играет далеко не ключевую роль, и падение производительности которого почти никак не скажется на работе предприятия. И противопоставляю ему «разработчика» — квалифицированного высокооплачиваемого работника, трата времени которого на погрузку мебели или починку сантехники — это прямые убытки. Если разработчик самовольно и без веских оснований начинает пи****сить байты и такты [меня уже банили за процитированный мат], то это в некоторых местах справедливо называют саботажем.
PD>>>Меня не интересует простота восприятия.
Q>>Павел, вы, видимо, не работаете в коллективе?
PD>Работаю. В сильно распределенном коллективе :-)
:D Павел, ну вы всерьёз, что ли? Ну кто вас учил так доказывать?
1) Предвзятость выборки и категорически некорректный её анализ. а) Вы сравниваете функции по значению в одной точке. Супер. Аналогичным способом можно заключить, что функция x + 10 в десять раз «больше» функции e^x, потому что это справедливо для точки x = 0. b) Значения функций в некоторой точке отличаются в 5 раз (скажем, 1 секунда и 5 секунд), но обе функции линейны — играет роль «константа». Какая — аддитивная или мультипликативная? Если увеличить размер массива в сто раз, то значения функций будут соотноситься в 5 раз или на 4 секунды? Или какое-то промежуточное значение? Ваше «доказательство» как-то обосновывает ваши «в пять раз»?
2) Не учтён контекст. Где и как будет вызываться код, на какие условия эксплуатации рассчитан? Например, если речь идёт о времени респонса на действие пользователя в GUI, то он может просто не заметить разницы во многих случаях. С точки зрения машины, он тупо медленно тягает мышь.
3) Не оценена систематическая ошибка. Вы уверены, что DateTime.Now подходящий инструмент? Или, быть может, лучше frequency counter'ы?
4) Оценка правдоподобия полученного результата. У вас она где? Есть проверка своего исследования? Вот я смотрю, а у вас там
нули суммируются. Это тоже распространённый случай исследовательской недобросовестности — не так тщательно проверять «удобные» результаты — именно этот случай отдельно оговаривал Фейнман в известной лекции, включённой главой «Культ Карго» в автобиографическую книжку.
PD>А что касается твоего примера — предполагай что хочешь, твое право, но пока ты не дашь доказательства твоего предположения (в секундах и миллисекундах), твое предположение ничего не стоит.
Презумпция невиновности «нулевой гипотезы» или «принцип отсутствия достаточных оснований». Нет достаточных оснований, чтобы считать LINQ виноватым.
Или — пока вы не сфотографируете свой мозг и не дадите пруфпик в студию, ваше предположение о его существовании «ничего не стоит». Примерно такого же уровня рассуждения, и вестись на них я не буду. Доказывать, что я не верблюд — тоже.
PD>Может, хватит всяких прочих утверждений ? Приведи время работы!
Не вижу на то оснований, чтобы что-то доказывать. Такова логика науки, читайте того же Имре Лакатоса или Карла Поппера. Существует бесконечное множество утверждений, причём неверных или бредовых неизмеримо больше. На всех времени не напасёшься, чтобы их опровергать. Чтобы заняться опровержением какой-то гипотезы, нужны основания. Пока что практика использования LINQ не даёт оснований всерьёз опасаться падения производительности в абсолютном большинстве задач. Ваша гипотеза о том, что LINQ-де безбожно тормозит, а циклы рвут его в клочья и вообще must use, пока что интересна не более, чем чайник Рассела.
>>Когда будет доказано — и не в попугаях, а в профилировщике (т.е. с учётом частоты выполнения участка кода) — только тогда и надо думать об оптимизации.
PD>В общем так. Все голословные утвреждения меня мало интересуют.
Утверждение о существовании у вас мозга не менее голословно. А ну-ка докажите! (Это просто пример, я не хочу обидеть, честно! Просто хочу объяснить, что в некоторых случаях вы не вправе требовать доказательств.)
PD>Равно как и рассуждения о том, что надо и что не надо оптимизировать. Это другой вопрос. Либо приводи время работы своей программы, либо не стоит продолжать.
В этой реплике содержится ложная пресуппозиция о том, что я должен — согласно логике дискуссии — приводить время какой-то программы. А это не так. Я говорю не в том смысле, что мне не интересно её приводить. И не в том ключе, мол, я не буду тратить на вас время. Я подчёркиваю — я и не должен обосновывать любое на ваш выбор утверждение. В дискуссии у оппонентов принципиально асимметричные роли, это важно понимать. В данном случае вы пытаетесь «сдвинуть парадигму» — убедить в малопригодности LINQ'а, а не наоборот — я вам пытаюсь его навязать.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, gandjustas, Вы писали:
PD>>>И что ? В том массиве, что я сделал, ее найти нельзя ? Кстати, если уж именно это надо — оборву цикл, как найду первую сумму, которая больше заданного, ибо дальше будет еще больше . И для этой задачи и массив-то совсем не нужен. Ни один. Суммируй в одну переменную пока сумма >= заданного не станет, и отмечай максимальную из четных.
G>>именно этим код со scan и занимается G>>Только возможностей по композиции у него гораздо больше. G>>Тебе же придется переписывать большую часть кода при незначительном изменении условий. PD>Придется.
Это и плохо.
G>>>>или еще как-то скомбинировать результирующую последовательность с другими операциями. PD>>>Кто мешает ? G>>Циклы мешают.
PD>Ты считаешь, что их реально нет в коде, сгенерированном LinQ ?
нету. Linq генерирует вызовы методов, а не циклы.
При обработке результатов Linq_ового выражения может вообще до цикклов не дойти.
PD>Или это просто продолжение предыдущего — что мне придется многое переписывать ? Если второе — да, согласен, но я не согласен с тем, что ради того, чтобы сделать жизнь программиста легче, можно позволить себе 5-6 кратное замедление.
Тебе про замедление QBit уже написал.
PD>А работать-то программа должна не в мозгу человека, а в машине!
Всё бы хорошо, вот только читает программу не машина а мозг.
PD>Кто же за бедную машину-то заступится ? Жалко ее. Столько бессмысленной работы делать!
Заступитесь за бедный мозг.
Здравствуйте, gandjustas, Вы писали:
G>>>Тебе же придется переписывать большую часть кода при незначительном изменении условий. PD>>Придется. G>Это и плохо.
С точки зрения объема моей работы, а с точки зрения качества продукта — наоборот.
PD>>Ты считаешь, что их реально нет в коде, сгенерированном LinQ ? G>нету. Linq генерирует вызовы методов, а не циклы.
Пусть он генерирует что ему вздумается, исполняться будет все равно цикл (явный или неявный). Или рекурсия. Других способов выполнения массовой операции нет.
G>При обработке результатов Linq_ового выражения может вообще до цикклов не дойти.
Если там нет необходимости выполнить массовую операцию — да, может. Но и я тогда цикл писать не буду.
PD>>Или это просто продолжение предыдущего — что мне придется многое переписывать ? Если второе — да, согласен, но я не согласен с тем, что ради того, чтобы сделать жизнь программиста легче, можно позволить себе 5-6 кратное замедление. G>Тебе про замедление QBit уже написал.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, gandjustas, Вы писали:
G>>>>Тебе же придется переписывать большую часть кода при незначительном изменении условий. PD>>>Придется. G>>Это и плохо.
PD>С точки зрения объема моей работы, а с точки зрения качества продукта — наоборот.
Чушь говоришь. Linq более декларативен, что уменьшает плотность ошибок на единицу функционала.
А твои циклы как раз способствуют увеличению.
PD>>>Ты считаешь, что их реально нет в коде, сгенерированном LinQ ? G>>нету. Linq генерирует вызовы методов, а не циклы.
PD>Пусть он генерирует что ему вздумается, исполняться будет все равно цикл (явный или неявный). Или рекурсия. Других способов выполнения массовой операции нет.
Ты опять неправ. При использовании Linq выражения может вообще цикл не выполняться.
G>>При обработке результатов Linq_ового выражения может вообще до цикклов не дойти. PD>Если там нет необходимости выполнить массовую операцию — да, может. Но и я тогда цикл писать не буду.
Только у тебя это будут совершенно разные случаи, а Linq позволит большую часть написать одинаково.
Это можно будет вынести отдельно, уменьшив тем самым объем кода и количество ошибок на единицу функционала.
PD>>>Или это просто продолжение предыдущего — что мне придется многое переписывать ? Если второе — да, согласен, но я не согласен с тем, что ради того, чтобы сделать жизнь программиста легче, можно позволить себе 5-6 кратное замедление. G>>Тебе про замедление QBit уже написал. PD>Меня демагогия мало интересует.
Это правда жизни. Во многих случаях разница в 5 раз по времени выполнения будет незаметна.
Зато разница в 5 раз по времени написанияя заметна всегда