Особенности языка mql5, тонкости и приёмы работы - страница 276

 

Немного более оптимизированная версия:


bool TimeToStructMQLplus(datetime timestamp, MqlDateTime& dt_struct)
{
    static const int Months[] = { 0, 11512692, 11512196, 11511744, 11511248, 11510766, 11510272, 11509790, 11509296, 11508797, 11508318, 11507822, 11507342 };

    const uint t            = (uint)timestamp;
    const int  n            = (int)(t / 86400);
    const int  tn           = (n << 2) | 2;

    dt_struct.day_of_year   = (tn % 1461) >> 2;
    dt_struct.year          = (tn / 1461) + 1970;
    const int  isleap       = !(dt_struct.year & 3);

    dt_struct.mon           = ((((dt_struct.day_of_year + ((dt_struct.day_of_year < (isleap + 59)) ? 0 : (2 - isleap))) * 12) + 373) / 367);
    dt_struct.day           = n - (int)((dt_struct.year * 5844 - Months[dt_struct.mon]) >> 4);
    #ifndef  WITHOUT_HOURS
        dt_struct.hour      = (int)(t / 3600) % 24;
        dt_struct.min       = (int)(t / 60) % 60;
        dt_struct.sec       = (int)(t % 60);

    #endif //#ifndef WITHOUT_HOURS
    dt_struct.day_of_week   = (n + 4) % 7;

   return (true);
}


Результаты:


Compiler Version: 4620 AVX2 + FMA3, optimization - true
12 th Gen Intel Core i7-12700 K, AVX2 + FMA3
With hours (dt.hour+ dt.min+ dt.sec - on), random datetimes[].
1970.01.01 00:00:35 - 2097.11.29 23:59:51
 4.87 ns, checksum = 1235575018417502   // TimeToStruct2100
 4.43 ns, checksum = 1235575018417502   // TimeToStructFast
 5.12 ns, checksum = 1235575018417502   // TimeToStructFast_fxsaber
 4.83 ns, checksum = 1235575018417502   // TimeToCalendar
10.17 ns, checksum = 1235575018417502   // TimeToJulian
 4.29 ns, checksum = 1235575018417502   // TimeToStructMQLplus
21.04 ns, checksum = 1235575018417502  /// MQL's TimeToStruct()

Compiler Version: 4620 AVX, optimization - true
12 th Gen Intel Core i7-12700 K, AVX2 + FMA3
With hours (dt.hour+ dt.min+ dt.sec - on), random datetimes[].
1970.01.01 00:00:03 - 2097.11.29 23:59:19
 4.46 ns, checksum = 1240645497052022   // TimeToStruct2100
 4.19 ns, checksum = 1240645497052022   // TimeToStructFast
 4.71 ns, checksum = 1240645497052022   // TimeToStructFast_fxsaber
 4.51 ns, checksum = 1240645497052022   // TimeToCalendar
 9.38 ns, checksum = 1240645497052022   // TimeToJulian
 3.97 ns, checksum = 1240645497052022   // TimeToStructMQLplus
19.64 ns, checksum = 1240645497052022  /// MQL's TimeToStruct()

Compiler Version: 4620 X64 Regular, optimization - true
12 th Gen Intel Core i7-12700 K, AVX2 + FMA3
With hours (dt.hour+ dt.min+ dt.sec - on), random datetimes[].
1970.01.01 00:00:12 - 2097.11.29 23:59:10
 4.32 ns, checksum = 1237792403157277   // TimeToStruct2100
 4.02 ns, checksum = 1237792403157277   // TimeToStructFast
 4.68 ns, checksum = 1237792403157277   // TimeToStructFast_fxsaber
 4.15 ns, checksum = 1237792403157277   // TimeToCalendar
 8.70 ns, checksum = 1237792403157277   // TimeToJulian
 3.89 ns, checksum = 1237792403157277   // TimeToStructMQLplus
19.82 ns, checksum = 1237792403157277  /// MQL's TimeToStruct()
Файлы:
 
Dominik Egert #:

Немного более оптимизированная версия:



Результаты:


Отличный Доминик, вы смогли побить рекорд в 5 наносекунд в этом видео https://youtu.be/0s9F4QWAl-E?si=ZzdFCrFtU8Ean2NJ&amp;t=590

 
Dominik Egert #:

Немного более оптимизированная версия:

Ого! Первая версия, стабильно лучшая на всех процессорах (x86/AVX/AVX2).

Только наверное надо сделать скрипт для тестирования на правильность всех алгоритмов. Это просто, ИМХО. В цикле по датам сравнивать все результаты расчётов со встроенной функцией.

 
amrali #:
Отличный Доминик, вы смогли побить рекорд в 5 наносекунд в этом видео https://youtu.be/0s9F4QWAl-E?si=ZzdFCrFtU8Ean2NJ&amp;t=590


Думаю, это связано с процессором. Было бы интересно увидеть результаты на i9 14900KS или другом процессоре высшего класса.
 
Dominik Egert #:

Немного более оптимизированная версия:



Результаты:


AVX2 медленнее, чем X64? Странно.
 
Alain Verleyen #:
AVX2 медленнее, чем X64? Странно.

Подозреваю, что компилятор MQL применяет расширения AVX только к двойным значениям. Возможно, при компиляции через AVX-расширения управление памятью происходит иначе.

Возможно, оптимизатор пропускает некоторые x86-оптимизации, когда ищет AVX-оптимизации.

Было бы интересно получить заявление от MQ по этому поводу.
 
Edgar Akhmadeev #:

Вот это да! Первая версия, неизменно лучшая на всех процессорах (x86/AVX/AVX2).

Просто, наверное, стоит сделать скрипт для проверки корректности всех алгоритмов. Это просто, ИМХО. В цикле даты сравниваем все результаты вычислений со встроенной функцией.


Видимо, имеется в виду подмножество ISA, а не процессор...

BTW, процессоры AMD все еще поддерживают AVX512...

Хотя я не вижу в этом никакой пользы для задачи, которую мы пытаемся оптимизировать.

Однако мы могли бы попробовать сделать вычисления даты с использованием двоичных или плавающих чисел и посмотреть, сможем ли мы найти прирост производительности между различными подмножествами ISA.
 
Dominik Egert #:
BTW, процессоры AMD все еще поддерживают AVX512...

Мой AMD Ryzen 3 PRO 3200GE - нет. Мне кажется, его поддерживают серверные процессоры, но я не интересовался.

 
Edgar Akhmadeev #:
AMD Ryzen 3 PRO 3200GE
Извините, я не проверил ваш конкретный процессор. - Intel убрала AVX512 в процессорах 12-го поколения из-за проблем с совместимостью с эффективными ядрами. - Но у AMD он все еще есть.
 
Dominik Egert #:

Немного более оптимизированная версия:



Результаты:


Я давно заметил, что с компилятором MQL при выполнении бенчмарков происходит что-то странное,

Если количество сравниваемых функций превышает определенный предел ?!, то вы не получаете правильных результатов (т.е. функции в конце mq5-файла получают лучшие результаты с наименьшим временем выполнения, а верхние функции - плохие результаты). Такое уже случалось со мной, поэтому лучше ограничить сравниваемые функции до 3/4 максимума. Если у кого-то есть объяснение этому странному явлению, пожалуйста, просветите меня.

Это произошло и здесь, когда версия Доминика была добавлена в файл скрипта бенчмарка.

Чтобы получить более наглядное представление, я просто сохранил в исходном коде только две функции, и вот мои результаты в сравнении:

Compiler Version: 4620 X64 Regular, optimization - true
13 th Gen Intel Core i7-13700 KF, AVX2 + FMA3
With hours (dt.hour+ dt.min+ dt.sec - on), random datetimes[].
1970.01.01 00:00:18 - 2097.11.29 23:59:36
 3.87 ns, checksum = 1240831954764697   // TimeToStructFast
 3.83 ns, checksum = 1240831954764697   // TimeToStructMQLplus
18.53 ns, checksum = 1240831954764697  /// MQL's TimeToStruct()

Compiler Version: 4620 AVX, optimization - true
13 th Gen Intel Core i7-13700 KF, AVX2 + FMA3
With hours (dt.hour+ dt.min+ dt.sec - on), random datetimes[].
1970.01.01 00:00:02 - 2097.11.29 23:59:39
 4.07 ns, checksum = 1245293506380519   // TimeToStructFast
 4.08 ns, checksum = 1245293506380519   // TimeToStructMQLplus
18.57 ns, checksum = 1245293506380519  /// MQL's TimeToStruct()

Compiler Version: 4620 AVX2 + FMA3, optimization - true
13 th Gen Intel Core i7-13700 KF, AVX2 + FMA3
With hours (dt.hour+ dt.min+ dt.sec - on), random datetimes[].
1970.01.01 00:00:47 - 2097.11.29 23:59:41
 4.10 ns, checksum = 1295113651058133   // TimeToStructFast
 4.08 ns, checksum = 1295113651058133   // TimeToStructMQLplus
18.62 ns, checksum = 1295113651058133  /// MQL's TimeToStruct()

Одинаковая производительность, и обеим удалось опуститься ниже 5 наносекунд.

Файлы: