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

 
fxsaber #:
Почему второй вариант работает в 20 раз медленнее?
Трюк с memcpy(Array, Array, 0) для получения адреса — остроумный хак, но использовать его для поэлементного доступа к массиву — антипаттерн. DLL-вызовы имеют смысл только для batch-операций, где один вызов обрабатывает большой блок данных.
Если нужен низкоуровневый доступ к памяти в MQL5, лучше писать всю логику внутри одной DLL-функции, а не дёргать её миллионы раз из MQL.

Причина очевидна: overhead вызова DLL-функции на каждой итерации.
 

@amrali@Nikolai Semko, спасибо!

Я хотел реализовать прямой доступ к массиву без проверок на корректность индекса.

 
fxsaber #:

@amrali@Nikolai Semko, спасибо!

Я хотел реализовать прямой доступ к массиву без проверок на корректность индекса.

Лучший вариант - вся логика внутри C++ DLL
Но можно попробовать частичное решение через развёртку цикла
int i = 0;
for (; i <= Size - 8; i += 8) {
    Sum += Array[i]   + Array[i+1] + Array[i+2] + Array[i+3] +
           Array[i+4] + Array[i+5] + Array[i+6] + Array[i+7];
}

 
Nikolai Semko #:
Но можно попробовать частичное решение через развёртку цикла

Этот вариант в три раза медленнее.

 
fxsaber #:

Этот вариант в три раза медленнее.

Это подтверждает, что компилятор MQL5 умнее, чем кажется.
Судя по всему компилятор видит 8 разных индексов, 8 отдельных проверок границ на каждой итерации и в результате потеря автовекторизации (не распознаёт паттерн).
0.3 нс на итерацию - думаю это почти предел. Даже C++ DLL не даст большого выигрыша. Практически уперлись в пропускную способность памяти, а не CPU. 
Дальше только менять архитектуру решения. Возможно использование GPU (OpenCL) даст какие-то результаты, но это только в случае, если присутствуют многократные операции над одним буфером или более сложные вычисления чем просто сумма. Для однократной суммы — GPU может быть сопоставим или даже медленнее из-за transfer overhead.
 
Nikolai Semko #:
Возможно использование GPU (OpenCL) даст какие-то результаты, но это только в случае, если присутствуют многократные операции над одним буфером или более сложные вычисления чем просто сумма. Для однократной суммы — GPU может быть сопоставим или даже медленнее из-за transfer overhead.

ради любопытства сгенерил с помощью AI ассистента код теста с использованием OpenCL

2025.12.11 20:18:38.625 test_array_sum (EURUSD,M4)      ╔════════════════════════════════════════════════════════════╗
2025.12.11 20:18:38.625 test_array_sum (EURUSD,M4)      ║          CPU vs GPU BENCHMARK (OpenCL)                     ║
2025.12.11 20:18:38.625 test_array_sum (EURUSD,M4)      ╠════════════════════════════════════════════════════════════╣
2025.12.11 20:18:38.625 test_array_sum (EURUSD,M4)      ║  Elements: 100M | Data size: 381 MB
2025.12.11 20:18:38.625 test_array_sum (EURUSD,M4)      ╚════════════════════════════════════════════════════════════╝
2025.12.11 20:18:38.758 test_array_sum (EURUSD,M4)      
2025.12.11 20:18:38.758 test_array_sum (EURUSD,M4)      ▓▓▓ TEST 1: SIMPLE SUM (only +=) ▓▓▓
2025.12.11 20:18:38.786 test_array_sum (EURUSD,M4)      CPU: 28269 µs, sum = 5050000000
2025.12.11 20:18:38.786 test_array_sum (EURUSD,M4)      --- Simple GPU ---
2025.12.11 20:18:38.787 test_array_sum (EURUSD,M4)      OpenCL: GPU device 'Intel Iris Xe Graphics' selected
2025.12.11 20:18:39.187 test_array_sum (EURUSD,M4)        GPU load:    112267 µs
2025.12.11 20:18:39.187 test_array_sum (EURUSD,M4)        GPU compute: 27958 µs
2025.12.11 20:18:39.187 test_array_sum (EURUSD,M4)        GPU total:   140225 µs
2025.12.11 20:18:39.187 test_array_sum (EURUSD,M4)        Sum: 50500000002025.12.11 20:18:39.229 test_array_sum (EURUSD,M4)      
2025.12.11 20:18:39.229 test_array_sum (EURUSD,M4)      ▓▓▓ TEST 2: HEAVY COMPUTE (sin × cos) ▓▓▓
2025.12.11 20:18:40.568 test_array_sum (EURUSD,M4)      CPU: 1339550 µs, sum = -136000000
2025.12.11 20:18:40.568 test_array_sum (EURUSD,M4)      --- Heavy GPU ---
2025.12.11 20:18:41.019 test_array_sum (EURUSD,M4)        GPU load:    105231 µs
2025.12.11 20:18:41.019 test_array_sum (EURUSD,M4)        GPU compute: 27317 µs
2025.12.11 20:18:41.019 test_array_sum (EURUSD,M4)        GPU total:   132548 µs
2025.12.11 20:18:41.019 test_array_sum (EURUSD,M4)        Sum: -1360000002025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ╔════════════════════════════════════════════════════════════╗
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║                    RESULTS SUMMARY                         ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ╠════════════════════════════════════════════════════════════╣
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║ SIMPLE SUM (only +=):                                      ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   CPU:         28 ms
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   GPU total:   140 ms (load: 112 + compute: 27)
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   Winner:      CPU ✓ (5.0x faster)
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║                                                            ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║ HEAVY COMPUTE (sin × cos):                                 ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   CPU:         1339 ms
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   GPU total:   132 ms (load: 105 + compute: 27)
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   Winner:      GPU ✓ (10.1x faster)
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ╠════════════════════════════════════════════════════════════╣
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║                    CONCLUSIONS                             ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ╠════════════════════════════════════════════════════════════╣
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║ Memory bandwidth:                                          ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   CPU→GPU transfer: 3.31 GB/s
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   CPU throughput:   3.54 G elements/s
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   GPU throughput:   3.58 G elements/s
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║                                                            ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║ Recommendations:                                           ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   • Simple ops:    USE CPU (GPU 5.0x slower)
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   • Heavy compute: USE GPU (10.1x faster)
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║                                                            ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║ GPU is optimal when:                                       ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   • Data stays on GPU (pipeline)                           ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   • Heavy compute per element (sin, cos, sqrt, etc.)       ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ║   • Multiple passes over same data                         ║
2025.12.11 20:18:41.060 test_array_sum (EURUSD,M4)      ╚════════════════════════════════════════════════════════════╝


Важно понимать что это результат на очень слабой интегрированной ноутбучной видео карте c shared с ОЗУ памятью Intel Iris Xe Graphics.
Если поставить видеокарту примерно за 500 баксов (например NVIDIA RTX 4070), то скорость загрузки в память GPU увеличится в 4-5 раз, а скорость вычислений примерно в 10 раз в сравнении с моей картой. 

Ожидаемые результаты на RTX 4070

Метрика Iris Xe RTX 4070 Разница
GPU load (400 MB)   110 мс    ~25 мс*  4x
GPU compute (simple)   26 мс    ~2-3 мс  10x
GPU compute (heavy)   28 мс    ~2-3 мс  10x
Memory bandwidth ~3.6 GB/s    ~15-20 GB/s**   5x

*PCIe 4.0 x16 = ~25 GB/s теоретический
**Реальный через PCIe, не VRAM bandwidth

Интересно будет посмотреть результат этого теста для продвинутых видеокарт. Если есть у кого, покажите результат плиз.

PS  Второй тест загрузки массива в GPU всегда быстрее из-за кэшa L3, в котором оказывается наш массив. Особенно заметно при размере массива меньше размера L3 кеша. 


 

Файлы:
 
Nikolai Semko #:
Лучший вариант - вся логика внутри C++ DLL
Но можно попробовать частичное решение через развёртку цикла

и OMP там включить

https://learn.microsoft.com/ru-ru/cpp/parallel/openmp/reference/openmp-directives?view=msvc-170

https://stackoverflow.com/questions/27056090/how-to-parallelize-this-array-sum-using-openmp

OpenMP Directives
OpenMP Directives
  • TylerMSFT
  • learn.microsoft.com
Дополнительные сведения: Директивы OpenMP
 
Nikolai Semko #:

ради любопытства сгенерил с помощью AI ассистента код теста с использованием OpenCL

Сохранился диалог?

ЗЫ Получаю ERR_OPENCL_NOT_SUPPORTED.

 
fxsaber #:

Сохранился диалог?

ЗЫ Получаю ERR_OPENCL_NOT_SUPPORTED.

МТшные примеры работают? Возможно драйвера не стоят.

У меня такая проблема:

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

OpenCL в трейдинге

Rorschach, 2024.11.13 20:37

Поставил AMD APP SDK 3.0, терминал пишет opencl.dll not found, please install OpenCL drivers. Процессоры больше не поддерживаются? Сторонняя программа видит и рабает.


Nikolai Semko #:
потеря автовекторизации (не распознаёт паттерн)

Это проблема https://www.mql5.com/ru/forum/495741/page2#comment_58102015

Тест AVX512
Тест AVX512
  • 2025.09.22
  • www.mql5.com
Требуются добровольцы с avx512 Нужно скомпилировать и запустить скрипт в 4 режимах Поделиться результатами Дефолтные значения оптимальные можно SIZ...
 
╔════════════════════════════════════════════════════════════╗
║          CPU vs GPU BENCHMARK (OpenCL)                     ║
╠════════════════════════════════════════════════════════════╣
║  Elements: 100M | Data size: 381 MB
╚════════════════════════════════════════════════════════════╝

▓▓▓ TEST 1: SIMPLE SUM (only +=) ▓▓▓
CPU: 22857 µs, sum = 5050000000
--- Simple GPU ---
OpenCL: GPU device 'NVIDIA GeForce RTX 3060' selected
  GPU load:    73441 µs
  GPU compute: 1309 µs
  GPU total:   74750 µs
  Sum: 5050000000 ✓

▓▓▓ TEST 2: HEAVY COMPUTE (sin × cos) ▓▓▓
CPU: 1999283 µs, sum = -136000000
--- Heavy GPU ---
  GPU load:    75667 µs
  GPU compute: 1723 µs
  GPU total:   77390 µs
  Sum: -136000000 ✓

╔════════════════════════════════════════════════════════════╗
║                    RESULTS SUMMARY                         ║
╠════════════════════════════════════════════════════════════╣
║ SIMPLE SUM (only +=):                                      ║
║   CPU:         22 ms
║   GPU total:   74 ms (load: 73 + compute: 1)
║   Winner:      CPU ✓ (3.3x faster)
║                                                            ║
║ HEAVY COMPUTE (sin × cos):                                 ║
║   CPU:         1999 ms
║   GPU total:   77 ms (load: 75 + compute: 1)
║   Winner:      GPU ✓ (25.8x faster)
╠════════════════════════════════════════════════════════════╣
║                    CONCLUSIONS                             ║
╠════════════════════════════════════════════════════════════╣
║ Memory bandwidth:                                          ║
║   CPU→GPU transfer: 5.07 GB/s
║   CPU throughput:   4.38 G elements/s
║   GPU throughput:   76.39 G elements/s
║                                                            ║
║ Recommendations:                                           ║
║   • Simple ops:    USE CPU (GPU 3.3x slower)
║   • Heavy compute: USE GPU (25.8x faster)
║                                                            ║
║ GPU is optimal when:                                       ║
║   • Data stays on GPU (pipeline)                           ║
║   • Heavy compute per element (sin, cos, sqrt, etc.)       ║
║   • Multiple passes over same data                         ║
╚════════════════════════════════════════════════════════════╝