Бойтесь как огня массовых конвертаций вида (int)double или (double)int и вообще смешения int+double в мат операциях.
Это дает дичайший оверхед в процессоре - просто такая дорогая ассемблерная команда. Если считаете в double, продолжайте в нем считать и не переключайтесь в integer типы.
Команды вида cvtsi2sd/cvttsd2si очень долгие. Небольшая наводка в статье "Самая медленная инструкция x86", злодей номер 2.
Спасибо за весьма ценную статью.
Но если честно, я не понимаю почему тогда в этом простом скрипте:
#define Num 1000000voidOnStart()
{
double arr[Num];
for (int i=0;i<Num;i++) arr[i]=(double) rand()/(1+rand()%100); // инициализируем массив случайными числами double от 0.0 до 32767.0long sumL=0;
ulong t1=GetMicrosecondCount();
for (int i=0;i<Num;i++) sumL+=(long)arr[i]; // сумма long
t1=GetMicrosecondCount()-t1;
double sumD=0;
ulong t2=GetMicrosecondCount();
for (int i=0;i<Num;i++) sumD+=arr[i]; // сумма double
t2=GetMicrosecondCount()-t2;
Print ("Сумма long = "+ string(sumL)+ ", время суммирования "+string(t1)+" микросекунд");
Print ("Сумма double = "+ DoubleToString(sumD)+ ", время суммирования "+string(t2)+" микросекунд");
}
сумма long с конвертацией типа double в long осуществляется заметно быстрее, чем сумма double того же массива без конвертации
2019.01.1522:21:46.410 TestSpeedDoubleAndInt (NZDUSD,M5) Сумма long = 849290923, время суммирования 748 микросекунд
2019.01.1522:21:46.410 TestSpeedDoubleAndInt (NZDUSD,M5) Сумма double = 849764484.23059070, время суммирования 1393 микросекунд
Во первых, надо смотреть ассемблерный код и результат оптимизаций экстремально простых случаев(супермикросинтетика давно уже вводит в заблуждение). Тут легко нарваться на конвеерную реализацию, прям идеальный случай.
Во вторых, уже мало кто может гарантировать как скомпилируется и за сколько выполнится тот или иной код.
Достаточно добавить в код дополнительную строку/команду и скорость резко меняется. Реальный код/данные могут банально вылезти из L1/L2 кеша и все.
У вас как получилось? По теории/суперсинтетике кажется что целочисленные команды помогут в скорости, а в реальном коде слив. Потому что там кода в десятки/сотни раз больше, нет конвееризации, постоянное прыгание вычислений от целочисленных к вещественным и оптимизация ограничена.
Сверхбыстрый индикатор из сотен скользящих средних, реализованный на Canvas.
100 линий MA(шаг периода 10) - время расчета и вывода на экран - 4-7 миллисекунд
1000 линий MA(шаг периода 1) - время расчета и вывода на экран - 20-30 миллисекунд
код сильно не тестировал. Могут быть баги. Реализовано только для бара в толщину один пиксель (переводится принудительно в такой масштаб). Также не оптимизированна частота обновления экрана. Все линии расчитываются и полностью выводятся при каждом тике.
Все функции типа iMA, iAC, iMACD, iIchimoku и т.п., создают в глобальном кеше клиентского терминала копию соответствующего технического индикатора. Если копия индикатора с этими параметрами уже существует, то новая копия не создается, а увеличивается счетчик ссылок на данную копию. Эти функции возвращают хэндл соответствующей копии индикатора...
Оказывается, я смотрел частоту генерации полотна, а не частоту вывода.
Это разные числа, кратно отличающиеся.
Я оказывается чуть неправильно рассчитывал частоту генерации полотна (без вывода)и частоту вывода (без генерации)
Вот более корректный вариант.
Результаты на моем процессоре:
Если брать время чисто по формированию кадра из 200 сглаженных окружностей без вывода, то это происходит с частотой около 500 кадров в секунду.
формирование кадра из 200 несглаженных окружностей без вывода - около 1000 кадров в секунду.
Частота самой функции вывода изображения(полотна) на экран (функция Update) - это около 650 кадров в секунду.
Вы действительно потрудились на славу!
Бойтесь как огня массовых конвертаций вида (int)double или (double)int и вообще смешения int+double в мат операциях.
Это дает дичайший оверхед в процессоре - просто такая дорогая ассемблерная команда. Если считаете в double, продолжайте в нем считать и не переключайтесь в integer типы.
Команды вида cvtsi2sd/cvttsd2si очень долгие. Небольшая наводка в статье "Самая медленная инструкция x86", злодей номер 2.
Спасибо за весьма ценную статью.
Но если честно, я не понимаю почему тогда в этом простом скрипте:
сумма long с конвертацией типа double в long осуществляется заметно быстрее, чем сумма double того же массива без конвертации
Во первых, надо смотреть ассемблерный код и результат оптимизаций экстремально простых случаев(супермикросинтетика давно уже вводит в заблуждение). Тут легко нарваться на конвеерную реализацию, прям идеальный случай.
Во вторых, уже мало кто может гарантировать как скомпилируется и за сколько выполнится тот или иной код.
Достаточно добавить в код дополнительную строку/команду и скорость резко меняется. Реальный код/данные могут банально вылезти из L1/L2 кеша и все.
У вас как получилось? По теории/суперсинтетике кажется что целочисленные команды помогут в скорости, а в реальном коде слив. Потому что там кода в десятки/сотни раз больше, нет конвееризации, постоянное прыгание вычислений от целочисленных к вещественным и оптимизация ограничена.
А почему инициализация массивов любых типов в MQL4, более чем в 10 раз медленее чем в MQL5?
А почему инициализация массивов любых типов в MQL4, более чем в 10 раз медленее чем в MQL5?
Потому что там все массивы динамические и язык в десяток раз медленнее.
Сверхбыстрый индикатор из сотен скользящих средних, реализованный на Canvas.
100 линий MA(шаг периода 10) - время расчета и вывода на экран - 4-7 миллисекунд
1000 линий MA(шаг периода 1) - время расчета и вывода на экран - 20-30 миллисекунд
код сильно не тестировал. Могут быть баги. Реализовано только для бара в толщину один пиксель (переводится принудительно в такой масштаб). Также не оптимизированна частота обновления экрана. Все линии расчитываются и полностью выводятся при каждом тике.
Сверхбыстрый индикатор из сотен скользящих средних, реализованный на Canvas.
100 линий MA(шаг периода 10) - время расчета и вывода на экран - 4-7 миллисекунд
1000 линий MA(шаг периода 1) - время расчета и вывода на экран - 20-30 миллисекунд
прикольно, через стандартные индикаторы повисло бы все наглухо
прикольно, через стандартные индикаторы повисло бы все наглухо
а еще бы был километр кода...
может быть даже это можно сделать только с помощью шаблона. Не в курсе на счет ограничений количества линий индикатора в теле одного индикатора.
...
Не в курсе на счет ограничений количества линий индикатора в теле одного индикатора.
Ограничение есть. До 512 индикаторных буфера можно сделать >>> https://www.mql5.com/ru/docs/indicators