Скачать MetaTrader 5

Ошибки, баги, вопросы - страница 2185

Andrey Khatimlianskii
60136
Andrey Khatimlianskii  
Vladimir Pastushak:

Те кто не читают и не покупают, много ли Вы купили товаров не понимая для чего товар ?

Может тогда все публиковать в блогах ?

Понять предназначение товара из инструкции?

Глупость. Скачаю, и пощупаю демку.

A100
5040
A100  
A100:

Приведенный код основан на недоработке компилятора

Результат: 1... а почему не 2 ?

При том что С++ сообщает при компиляции об ошибке, поскольку очевидно подходят обе функции и кроме того синтаксис не позволяет явно вызвать функцию (2)

Более того учитывая специфику MQL логичнее было бы сделать с точностью до наоборот - установить приоритет передачи параметра не по значению (как сейчас), а по const ссылке (преимущества чего особенно видны на примере строк)

void f(       string  ) { Print( __FUNCSIG__ ); } //1
void f( const string& ) { Print( __FUNCSIG__ ); } //2
string g() { return "ABCDEF4"; }
void OnStart()
{
          string text1 = "ABCDEF1";
    const string text2 = "ABCDEF2";
//  вызываемая функция: сейчас  предлагается
    f( text1 );     //    1       2               
    f( text2 );     //    *       2 потому что const или оставить *
    f( "ABCDEF3" ); //    1       1
    f( g());        //    1       1
//Примечание: * - неопределенность
}

Непонятно зачем передавать (фактически копировать) длинющие строки по значению когда это можно делать по ссылке 

A100
5040
A100  

Ошибка при компиляции

#import  "Test.dll" //Error: '#import' - #import was not closed
#include "Test.h"
#import
//Test.h
void f();

А зачем вручную переносить содержимое .h файла (тем более что оно может периодически меняться) если его можно просто включить?

Nexxtor
654
Nexxtor  

Добрый день, подскажите:

Как записать результаты оптимизации в файл при использовании Local Network Farm или MQL5 Cloud Network ?

Есть процедура в OnTester(), использует:

string toWrite = "test";
fileHandle=FileOpen(fileName,FILE_CSV|FILE_READ|FILE_WRITE|FILE_ANSI|FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_COMMON,",");
FileWrite(fileHandle,toWrite);
FileClose(fileHandle);

При использовании Local агентов файл с результатами оптимизации создается в общей папке, при использовании Local Network Farm или MQL5 Cloud Network файла нет.

Тестирование стратегий - Алгоритмический трейдинг, торговые роботы - MetaTrader 5
Тестирование стратегий - Алгоритмический трейдинг, торговые роботы - MetaTrader 5
  • www.metatrader5.com
Тестер стратегий позволяет тестировать и оптимизировать торговые стратегии (советники) перед началом использования их в реальной торговле. При тестировании советника происходит его однократная прогонка с начальными параметрами на исторических данных. При оптимизации торговая стратегия прогоняется несколько раз с различным набором параметров...
MetaQuotes
Админ
26170
Renat Fatkhullin  
Nikolai Semko:ЧТО НЕ ТАК? ОТКУДА ТОРМОЗА?

Проверка показала, что:

  1. SQRT маппятся в прямые CPU инструкции

  2. SQRT + математические вычисления идут без ветвлений и за одну команду (128 бит данные) вычисляется сразу два корня

    Вот этот код превращается в следующий ассемблерный SSE код:
             D1=sqrt((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y));
             D2=sqrt((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y));
             D3=sqrt((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y));
             D4=sqrt((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y));
             D5=sqrt((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y));
             D6=sqrt((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y));
             D7=sqrt((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y));
             D8=sqrt((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y));
            ...
            sqrtsd  xmm1, xmm1
            unpcklpd        xmm4, xmm4
            movapd  xmm3, xmmword ptr [rsp + 432]
            unpcklpd        xmm3, xmmword ptr [rsp + 384]
            subpd   xmm3, xmm4
            mulpd   xmm3, xmm3
            unpcklpd        xmm0, xmm0
            movapd  xmm5, xmmword ptr [rsp + 416]
            unpcklpd        xmm5, xmmword ptr [rsp + 400]
            subpd   xmm5, xmm0
            mulpd   xmm5, xmm5
            addpd   xmm5, xmm3
            sqrtpd  xmm8, xmm5
            movapd  xmm5, xmmword ptr [rsp + 464]
            subpd   xmm5, xmm4
            mulpd   xmm5, xmm5
            movapd  xmm7, xmm9
            subpd   xmm7, xmm0
            mulpd   xmm7, xmm7
            addpd   xmm7, xmm5
            movapd  xmm6, xmm10
            unpcklpd        xmm6, xmm11
            subpd   xmm6, xmm4
            movapd  xmm3, xmmword ptr [rsp + 368]
            unpcklpd        xmm3, xmmword ptr [rsp + 352]
            subpd   xmm3, xmm0
            movapd  xmm4, xmm8
            shufpd  xmm4, xmm4, 1
            sqrtpd  xmm5, xmm7
            mulpd   xmm6, xmm6
            mulpd   xmm3, xmm3
            addpd   xmm3, xmm6
            sqrtpd  xmm15, xmm3
            movapd  xmm0, xmm14
            unpcklpd        xmm0, xmmword ptr [rsp + 336]
            subpd   xmm0, xmm2
            mulpd   xmm0, xmm0
            movapd  xmm2, xmm0
            shufpd  xmm2, xmm2, 1
            addsd   xmm2, xmm0
            movapd  xmm0, xmm15
            shufpd  xmm0, xmm0, 1
            sqrtsd  xmm12, xmm2
    Это произведение исскуства вообще-то. 8 корней вычислено за 4 вызова ассемблерной команды. Два double числа вычислялись за один вызов.

  3. При операциях через массив все идет штатно, с проверками, ветвлениями и потерями на конвертации double -> integer index

  4. При работе с массивами в этом примере идет постоянное смешение FPU/ALU, что очень плохо сказывается на производлительности

  5. Оптимизация доступа к динамическому массиву отличная, выше похвал. Но смешение FPU/ALU операций + перевод double -> integer + ветвления тратят время

Общий вывод: математика в MQL5 побеждает за счет идеальной оптимизации. Тут не массивы проигрывают, а математика выигрывает.

MetaQuotes
Админ
26170
Renat Fatkhullin  

А вот какую порнографию сделал на том же коде Visual C++ 2017 x64 с полными оптимизациями:

; 52   :       int X=pos%Width;
; 53   :       int Y=int(pos/Width);
; 54   :       
; 55   :       D1=sqrt((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y));

  0046f 0f 28 c8         movaps  xmm1, xmm0
  00472 8b c3            mov     eax, ebx
  00474 99               cdq
  00475 45 0f 57 db      xorps   xmm11, xmm11
  00479 f7 ff            idiv    edi
  0047b 0f 57 f6         xorps   xmm6, xmm6
  0047e 41 0f 28 c4      movaps  xmm0, xmm12
  00482 f2 44 0f 2a d8   cvtsi2sd xmm11, eax
  00487 f2 0f 2a f2      cvtsi2sd xmm6, edx
  0048b f2 41 0f 5c cb   subsd   xmm1, xmm11
  00490 f2 0f 5c c6      subsd   xmm0, xmm6
  00494 f2 0f 59 c9      mulsd   xmm1, xmm1
  00498 f2 0f 59 c0      mulsd   xmm0, xmm0
  0049c f2 0f 58 c1      addsd   xmm0, xmm1
  004a0 e8 00 00 00 00   call    sqrt

; 56   :       D2=sqrt((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y));
; 57   :       D3=sqrt((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y));

  004a5 41 0f 28 cf      movaps  xmm1, xmm15
  004a9 41 0f 28 c6      movaps  xmm0, xmm14
  004ad f2 0f 5c c6      subsd   xmm0, xmm6
  004b1 f2 41 0f 5c cb   subsd   xmm1, xmm11
  004b6 f2 0f 59 c0      mulsd   xmm0, xmm0
  004ba f2 0f 59 c9      mulsd   xmm1, xmm1
  004be f2 0f 58 c1      addsd   xmm0, xmm1
  004c2 e8 00 00 00 00   call    sqrt

; 58   :       D4=sqrt((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y));

  004c7 f2 0f 10 8c 24
        90 01 00 00      movsd   xmm1, QWORD PTR Y4$1$[rsp]
  004d0 f2 0f 10 84 24
        98 01 00 00      movsd   xmm0, QWORD PTR X4$1$[rsp]
  004d9 f2 41 0f 5c cb   subsd   xmm1, xmm11
  004de f2 0f 5c c6      subsd   xmm0, xmm6
  004e2 f2 0f 59 c9      mulsd   xmm1, xmm1
  004e6 f2 0f 59 c0      mulsd   xmm0, xmm0
  004ea f2 0f 58 c1      addsd   xmm0, xmm1
  004ee e8 00 00 00 00   call    sqrt

; 59   :       D5=sqrt((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y));
; 60   :       D6=sqrt((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y));
; 61   :       D7=sqrt((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y));
; 62   :       D8=sqrt((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y));

  004f3 f2 0f 10 44 24
        20               movsd   xmm0, QWORD PTR X8$1$[rsp]
  004f9 41 0f 28 c8      movaps  xmm1, xmm8
  004fd f2 0f 5c c6      subsd   xmm0, xmm6
  00501 f2 41 0f 5c cb   subsd   xmm1, xmm11
  00506 f2 0f 59 c0      mulsd   xmm0, xmm0
  0050a f2 0f 59 c9      mulsd   xmm1, xmm1
  0050e f2 0f 58 c1      addsd   xmm0, xmm1
  00512 e8 00 00 00 00   call    sqrt
  00517 f2 0f 10 4c 24
        28               movsd   xmm1, QWORD PTR Y2$1$[rsp]
  0051d 41 0f 28 c5      movaps  xmm0, xmm13
  00521 f2 44 0f 10 44
        24 30            movsd   xmm8, QWORD PTR Y5$1$[rsp]
  00528 f2 41 0f 5c cb   subsd   xmm1, xmm11
  0052d f2 44 0f 10 54
        24 40            movsd   xmm10, QWORD PTR Y6$1$[rsp]
  00534 f2 0f 5c c6      subsd   xmm0, xmm6
  00538 f2 44 0f 10 64
        24 50            movsd   xmm12, QWORD PTR Y7$1$[rsp]
  0053f f2 45 0f 5c c3   subsd   xmm8, xmm11
  00544 f2 0f 10 7c 24
        38               movsd   xmm7, QWORD PTR X5$1$[rsp]
  0054a f2 45 0f 5c d3   subsd   xmm10, xmm11
  0054f f2 44 0f 10 4c
        24 48            movsd   xmm9, QWORD PTR X6$1$[rsp]
  00556 f2 45 0f 5c e3   subsd   xmm12, xmm11
  0055b f2 44 0f 10 5c
        24 58            movsd   xmm11, QWORD PTR X7$1$[rsp]
  00562 f2 0f 5c fe      subsd   xmm7, xmm6
  00566 f2 0f 59 c0      mulsd   xmm0, xmm0
  0056a f2 44 0f 5c ce   subsd   xmm9, xmm6
  0056f f2 0f 59 c9      mulsd   xmm1, xmm1
  00573 f2 44 0f 5c de   subsd   xmm11, xmm6
  00578 f2 0f 58 c1      addsd   xmm0, xmm1
  0057c e8 00 00 00 00   call    sqrt
  00581 f2 0f 59 ff      mulsd   xmm7, xmm7
  00585 f2 45 0f 59 c0   mulsd   xmm8, xmm8
  0058a f2 41 0f 58 f8   addsd   xmm7, xmm8
  0058f 0f 28 c7         movaps  xmm0, xmm7
  00592 e8 00 00 00 00   call    sqrt
  00597 f2 45 0f 59 c9   mulsd   xmm9, xmm9
  0059c f2 45 0f 59 d2   mulsd   xmm10, xmm10
  005a1 f2 45 0f 58 ca   addsd   xmm9, xmm10
  005a6 41 0f 28 c1      movaps  xmm0, xmm9
  005aa e8 00 00 00 00   call    sqrt
  005af f2 45 0f 59 db   mulsd   xmm11, xmm11
  005b4 f2 45 0f 59 e4   mulsd   xmm12, xmm12
  005b9 f2 45 0f 58 dc   addsd   xmm11, xmm12
  005be 41 0f 28 c3      movaps  xmm0, xmm11
  005c2 e8 00 00 00 00   call    sqrt
  005c7 f2 0f 10 84 24
        88 01 00 00      movsd   xmm0, QWORD PTR Y1$1$[rsp]

; 63   : 
; 64   :       double d=fabs(D1+D3+D4+D8)/(D1+D2+D3+D4+D5+D6+D7+D8);

Безоговорочный кратный слив коду, который генерится в MQL5.

Удивительно, но у MSVC даже попыток оптимизации нет - всю математику гонит через библиотеки словно пишет под процессор 20 летней давности. И включение набора AVX команд нисколько не меняет поведения компилятора.

Тестовый C++ файл приложен. Мысль про "ошибка в тестовом примере" не надо высказывать, ошибки нет.

Файлы:
Test.cpp.zip 1 kb
Roffild
1520
Roffild  

У меня не строится график оптимизации по отрицательным значениям.

Данные в результатах оптимизации имеются.

Попробуйте в своих советниках задавать отрицательные значения. Значения можно * -1 для проверки.

Nikolai Semko
3319
Nikolai Semko  
Renat Fatkhullin:

Проверка показала, что:

  1. SQRT маппятся в прямые CPU инструкции

  2. SQRT + математические вычисления идут без ветвлений и за одну команду (128 бит данные) вычисляется сразу два корня

    Вот этот код превращается в следующий ассемблерный SSE код:
    Это произведение исскуства вообще-то. 8 корней вычислено за 4 вызова ассемблерной команды. Два double числа вычислялись за один вызов.

  3. При операциях через массив все идет штатно, с проверками, ветвлениями и потерями на конвертации double -> integer index

  4. При работе с массивами в этом примере идет постоянное смешение FPU/ALU, что очень плохо сказывается на производлительности

  5. Оптимизация доступа к динамическому массиву отличная, выше похвал. Но смешение FPU/ALU операций + перевод double -> integer + ветвления тратят время

Общий вывод: математика в MQL5 побеждает за счет идеальной оптимизации. Тут не массивы проигрывают, а математика выигрывает.

Спасибо большое за ценную информацию.

Новости, конечно же, больше радостные. Это реально круто!

Я всегда говорил, что MQ красавцы!

Но я также понимаю , что нужно быть крайне аккуратным со смешением типов данных. Но предупрежден - значит вооружен.
Было бы здорово от разработчиков получить какие-то рекомендации в этом свете.

Сейчас поэксперементирую с типами как обычных переменных так и массивов. Интересно что получиться. 

Nikolai Semko
3319
Nikolai Semko  
Renat Fatkhullin:

Поэкспериментировал.

Что-то у меня все равно пазлы не сходятся.

Сделал два варианта. Первый -по максимуму все перевел на тип int. Второй - на double.

Да, стало чуть быстрее. Но основные тормоза все равно присутствуют.

Вот с вариантом int главный тормозной блок:

 if(arr)
        {  // расчет квадратных корней через массив значений SQRT[]
         D1=SQRT[((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))];
         D2=SQRT[((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y))];
         D3=SQRT[((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y))];
         D4=SQRT[((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y))];
         D5=SQRT[((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y))];
         D6=SQRT[((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y))];
         D7=SQRT[((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y))];
         D8=SQRT[((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y))];
        }

в нем только тип int и нет никакого смешения типов. При этом и сам массив SQRT стал int. 

Pаботает он только на процентов  10 быстрее.

C вариантом double похожая картина.

Ну все одинаковое, только в одном случае идет вычисление функции sqrt(), при этом там происходит смешение типов.

А во втором случае идет обращение к int массиву и нет никакого смешения типов  и по идее должен использоваться только ALU.

И при этом второй вариант в 3 раза медленнее. Ну как не крути причина - массив.

И еще один важный момент.

В примере int если канвас размером 100x100, т.е. с такими параметрами

то при обращении к массиву мы получаем выйгрыш в скорости. 

Т.е. когда используем  массив SQRT размером 20 000, мы в выигрыше 15-20%, а когда размером 3 000 000, то проигрыш 200% при абсолютно одинаковой математике.

Выходит размер массива причина тормозов?

Файлы:
LSD_int.mq5 10 kb
MetaQuotes
Админ
26170
Renat Fatkhullin  

Люди давно потеряли способность понимать результаты современных С++ компиляторов.

К тому же у вас винегрет/мусор из кода, что означает практически нулевую возможность выстроить наивные аксиомы «если такие условия, то результат получится такой». То есть, итоговая оптимизация настолько все перестроит, что ваши гипотезы будут давать на десятки процентов разные результаты даже при мизерных изменениях в коде.

Взгляните еще раз на утрамбовку 8 корней в 4 ассемблерные команды и поймите, что вы не имеете шанса что-либо утверждать, требовать или аппелировать к своей логике. Оптимизаторы давно уже работают на запредельных уровнях, недоступных программистам.

То, как компилятор разложил корни, является исскуством. А вы пытаетесь побить это массивами, даже не понимая простейшего ограничения - чтение из массива это уже провал. Идеальная регистровая работа и пакетное вычисление корней против ветвлений(штрафы) и лазанию в память с частыми промахами в кеш.

Вы задаете вопрос «почему на мелком буфере быстрее работает, а на большом оглушительно сливает» потому, что вообще не знаете о L1/L2/L3 кешах процессора. Попали в кеш - посчитали быстро. Не попали - ждите пару десятков циклов чтения данных из верхнего кеша или памяти.