Новая версия платформы MetaTrader 5 build 4260: общие улучшения - страница 3

 
Slava #:

PS по поводу ускорений-замедлений. Принято прикладывать таблички с замерами времени. При этом, запуски должны производиться в одинаковых условиях и не менее 5 раз

Вот такие замеры (пункт Benchmark здесь).

Benchmark mode.
Getting Ticks (2024.01.01 00:00:00 - 2024.03.19 00:00:00)...
"TESTER_EURUSD" "TESTER_USDJPY"
1. TESTER_EURUSD: 2711808 ticks (2024.01.02 00:00:00 - 2024.03.18 23:59:55)
2. TESTER_USDJPY: 3597511 ticks (2024.01.02 00:00:00 - 2024.03.18 23:59:59)
Calculating (CLASSIC) 6309319 ticks...
1/5: Performance = 4 119 069.6 [00:00:01.531](100.00%), Best = 4 119 069.6 ticks/sec [00:00:01.531]
Calculating (CLASSIC) 6309319 ticks...
2/5: Performance = 4 120 985.1 [00:00:01.531](100.00%), Best = 4 120 985.1 ticks/sec [00:00:01.531]
Calculating (CLASSIC) 6309319 ticks...
3/5: Performance = 4 127 131.3 [00:00:01.528](100.00%), Best = 4 127 131.3 ticks/sec [00:00:01.528]
Calculating (CLASSIC) 6309319 ticks...
4/5: Performance = 4 103 139.0 [00:00:01.537](99.42%), Best = 4 127 131.3 ticks/sec [00:00:01.528]
Calculating (CLASSIC) 6309319 ticks...
5/5: Performance = 4 093 449.0 [00:00:01.541](99.18%), Best = 4 127 131.3 ticks/sec [00:00:01.528]
-----------------
BestPerformance = 4 127 131.3 ticks/sec [00:00:01.528]


Результаты.

void OnStart() { OnStart2(); }                                      // BestPerformance = 13 423 614.7 ticks/sec [00:00:00.172]
void OnInit()  { OnStart2(); }                                      // BestPerformance = 13 153 143.2 ticks/sec [00:00:00.176]
void OnInit()  { OnStart2(); ExpertRemove(); }                      // BestPerformance = 12 965 346.3 ticks/sec [00:00:00.178]
int OnInit()   { OnStart2(); return(INIT_FAILED); }                 // BestPerformance = 12 707 555.1 ticks/sec [00:00:00.182]
int OnInit()   { OnStart2(); ExpertRemove(); return(INIT_FAILED); } // BestPerformance = 13 084 818.3 ticks/sec [00:00:00.177]
Свой тиковый Тестер.
Свой тиковый Тестер.
  • 2024.03.24
  • www.mql5.com
В общее пользование выложен исходник  тикового тестера. Разберем его особенности. Лаконичность. Все спрятано в обертку, поэтому весь исходник выглядит так. #property script_show_inputs
 
b4260, отсутствует оптимизация компилятора.
#define BENCH(A)                                                             \
  {                                                                          \
    const ulong StartTime = GetMicrosecondCount();                           \
    A;                                                                       \
    Print(#A + ":" + (string)(GetMicrosecondCount() - StartTime) + " mcs."); \
  } 
  
struct A
{
  int i;
  double d;
  bool b;

  void Init()
  {
    this.i = 1;
    this.d = 1;
    this.b = 1;
  }
};

int Bench1()
{
  A Array[];
  
  for (uint i = ArrayResize(Array, 1e7); (bool)i--;)
  {
    Array[i].i = 1;
    Array[i].d = 1;
    Array[i].b = 1;
  }
  
  return(0);
}

int Bench2()
{
  A Array[];    

  for (uint i = ArrayResize(Array, 1e7); (bool)i--;)
    Array[i].Init();
  
  return(0);
}

void OnStart()
{
  for (int i = 0; i < 5; i++)
  {
    BENCH(Bench1()); // Bench1():205161 mcs.
    BENCH(Bench2()); // Bench2(): 80991 mcs. 
  }
}

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

Строка для поискаOshibka 104.

 
fxsaber #:

Вот такие замеры (пункт Benchmark здесь).


Результаты.

Но тут нет 10% разницы. ExpertRemove скорее всего экономит время на процедуру подсчета статистик на штатном завершении и сразу завершает программу. Init failed аналогично экономит завершение.

Плюс роль играет погрешность на замерах 180 мс на проход.

 
fxsaber #:
b4260, отсутствует оптимизация компилятора.

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

Строка для поискаOshibka 104.

В первом случае тройная проверка индексированного доступа, а во второй одно индексирование с последовательным заполнение одного блока, что хорошо оптимизируется. Требования безопасности языка не позволяет пропускать контроль индексного доступа.


Мы уже пару месяцев работаем над новой версией компилятора, где оптимизация будет гораздо лучше. Возможно, справимся с такими случаями последовательного обращения к одинаково индексируемым объектам.

 
Renat Fatkhullin #:

Но тут нет 10% разницы.

К сожалению, не сохранил OnStart2, что показывал такую разницу.

ExpertRemove скорее всего экономит время на процедуру подсчета статистик на штатном завершении и сразу завершает программу. Init failed аналогично экономит завершение.

Замер времени внутри OnStart2. Никакого отношения к ExpertRemove не имеет.

Плюс роль играет погрешность на замерах 180 мс на проход.

Увеличил в несколько раз длительность.

void OnStart() { OnStart2(); }                                      // BestPerformance = 13 688 465.0 ticks/sec [00:00:01.083]
void OnInit()  { OnStart2(); }                                      // BestPerformance = 13 661 990.1 ticks/sec [00:00:01.085]
void OnInit()  { OnStart2(); ExpertRemove(); }                      // BestPerformance = 12 972 229.3 ticks/sec [00:00:01.143]
int OnInit()   { OnStart2(); return(INIT_FAILED); }                 // BestPerformance = 12 385 010.1 ticks/sec [00:00:01.197]
int OnInit()   { OnStart2(); ExpertRemove(); return(INIT_FAILED); } // BestPerformance = 12 985 129.2 ticks/sec [00:00:01.142]

Разница 9%. Все такая же зависимость от void/int OnInit и ExpertRemove.


У меня просто оптимизация в одном случае идет условно 100 секунд, в другом - ~110. Это невозможно не заметить. Воспроизводится всегда.

 
Renat Fatkhullin #:

Требования безопасности языка не позволяет пропускать контроль индексного доступа.

Не знал, что на каждом Array[i] идет проверка 0<=i<Array.Size().

Мы уже пару месяцев работаем над новой версией компилятора, где оптимизация будет гораздо лучше. Возможно, справимся с такими случаями последовательного обращения к одинаково индексируемым объектам.

Получается, что можно ускорить и такое.

const int Size = ArraySize(Array);

for (int i = 0; i < Size; i++)
  Array[i] =  Value;


В матрицах и векторах такой же конроль идексного доступа?

 
fxsaber #:

Не знал, что на каждом Array[i] идет проверка 0<=i<Array.Size().

b4260, ArrayRemove для массивов простых структур работает медленнее решения с контролем индексного доступа.

Т.е. простой сдвиг влево одинакового куска памяти работает медленнее кастомного решения.

#define BENCH(A)                                                             \
  {                                                                          \
    const ulong StartTime = GetMicrosecondCount();                           \
    A;                                                                       \
    Print(#A + ":" + (string)(GetMicrosecondCount() - StartTime) + " mcs."); \
  } 
  
template <typename T>
int Bench1( int Start, int Count, const int SizeMem = 1e7 )
{
  T Array[];
  
  const int Koef = sizeof(MqlTick) / sizeof(T);

  Start *= Koef;
  Count *= Koef;
  
  ArrayResize(Array, SizeMem * Koef); // Выделяем одинаковый объем памяти (не зависит от T).
    
  ArrayRemove(Array, Start, Count);   // Сдвигаем на одинаковое число байтов влево (не зависит от T).
  
  return(ArraySize(Array));
}

template <typename T>
int Bench2( int Start, int Count, const int SizeMem = 1e7 )
{
  T Array[];    

  const int Koef = sizeof(MqlTick) / sizeof(T);

  Start *= Koef;
  Count *= Koef;

  const int Size = ArrayResize(Array, SizeMem * Koef); // Выделяем одинаковый объем памяти (не зависит от T).
  
  // Сдвигаем на одинаковое число байтов влево (не зависит от T).
  for (int i = Start, j = Start + Count; j < Size; i++, j++)
    Array[i] = Array[j];      
  
  return(ArrayResize(Array, MathMax(0, Size - Count)));
}

void OnStart()
{
  for (int i = 0; i < 5; i++)
  {
    BENCH(Bench1<MqlTick>(10, 1)); // Bench1<MqlTick>(10, 1):159674 mcs.
    BENCH(Bench2<MqlTick>(10, 1)); // Bench2<MqlTick>(10, 1):144041 mcs - самый быстрый.

    BENCH(Bench1<int>(10, 1)); // Bench1<int>(10, 1):156502 mcs. - идентичный сдвиг куска памяти влево.
    BENCH(Bench2<int>(10, 1)); // Bench2<int>(10, 1):385175 mcs.

    Print("------------");
  }
}

Строка для поискаOshibka 105.

 
Краши по несколько раз в час на последней релизной мт5 всё ещё на месте https://www.mql5.com/ru/forum/455977/page37#comment_51417941
 

А можно завести флажков про то что:

ChartFirst, OrdersTotal, OrdersHistoryTotal, SymbolsTotal,CustomTicksAdd, CustomRatesUpdate, ObjectsTotal

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

по логике зачастую их можно и переповторить позже. Это не столь критично как потеря темпа. 

 
Здравствуйте. Нейросети - это конечно, очень замечательно и современно, но не могли бы вы починить отсутствие торговых часов в субботу и воскресенье при импорте символа из json, не смотря на то, что в исходном символе они были включены? Этой баге уже много лет... Очень не удобно... И можно вернуть переход к определению по ctrl+click (вместо или вместе с кликом колесиком)? Пару версий назад ввели, но почему то с очередным обновлением снова вывели... Когда работаешь одновременно с другой полноценной IDE - постоянно путаешься и очень не удобно...