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

 
fxsaber #:

В реальности TimeToStruct редко используется

В целом согласен, но буквально на днях была задача, когда TimeToStruct использовалась около 1000 раз а сек. Мелочь конечно, но приятная мелочь. 
Могу допустить, что будут и другие подобные  задачи. Свой вариант сделал с кешированием.
 
Nikolai Semko #:
В целом я согласен, но буквально на днях была задача, в которой TimeToStruct использовался около 1000 раз в секунду. Мелочь, конечно, но приятная мелочь.
Могу предположить, что будут и другие подобные задачи. Я сделал свой вариант с кэшированием.
1000 раз в секунду? Я не могу представить, как это возможно?
 

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

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

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

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

fxsaber, 2024.05.06 23:50

void TimeToStruct2100_fxsaber( const datetime dt, MqlDateTime &dt_struct )
{
  const uint time = (uint)dt;
  
  dt_struct.sec = (int)(time % 60);
  dt_struct.min = (int)(time / 60) % 60;
  dt_struct.hour = (int)(time / 3600) % 24;
  
  dt_struct.day_of_year = (int)(time / (24 * 3600));
  dt_struct.day_of_week = (dt_struct.day_of_year + THURSDAY) % 7;
  
  const int Year = ((dt_struct.day_of_year << 2) + 2) / (365 * 4 + 1); // to 2100
  const bool Flag = ((Year & 3) == 2);
  
  dt_struct.day_of_year -= Year * 365 + ((Year + 2) >> 2);
//  dt_struct.day_of_year -= ((Year * 1461 + 1) >> 2) + Flag;
  
  dt_struct.year = Year + 1970;
  
  dt_struct.mon = (dt_struct.day_of_year + Flag) < 31 ? 1 : (dt_struct.day_of_year * 5 + 166) / 153;
  
  static const int Months[] = {0, 0-1, 31-1, 59-1, 90-1, 120-1, 151-1, 181-1, 212-1,243-1, 273-1, 304-1, 334-1};
  
  dt_struct.day = dt_struct.day_of_year - Months[dt_struct.mon] + (Flag && (dt_struct.mon < 3));
  
  dt_struct.day_of_year += Flag;
  
  return;
}
Проскакивали и другие варианты. В итоге получили, похоже, самые быстрые в мире Time-формулы через MQL+MathTester.
Алгоритмическая или реальная оптимизация?
Алгоритмическая или реальная оптимизация?
  • 2024.04.16
  • www.mql5.com
Для ускорения оптимизации ТС делают следующее Увеличивают количество параллельных вычислительных потоков. Пробуют разные компиляторы. Переписывают код под особенности железа (OpenCL, GPU и т.д.)
 
Nikolai Semko #:
В целом согласен, но буквально на днях была задача, когда TimeToStruct использовалась около 1000 раз а сек. Мелочь конечно, но приятная мелочь. 
Могу допустить, что будут и другие подобные  задачи. Свой вариант сделал с кешированием.

Я использую кеширование, например, при вычислении HMAC SHA-256 ключа для REST-API, который вычисляется долго, а применяется несколько раз в минуту в случайные моменты.

Но функцию, имеющую точность 1 сек, и вызываемую многажды в секунду, я бы рассчитывал раз в секунду (т.е. контроль извне). Ваше решение - тоже вариант, но делать внутреннее кеширование в каждом подобном случае похоже на костыли.

 
Alain Verleyen #:
1000 раз в секунду? Я не могу представить, как это возможно?

Ну может я слегка преувеличил насчет 1000, но несколько сотен раз в секунду это точно. Для 4K экранов может и 1000. 
Шкала времени для динамического чарта в пиковую нагрузку

 


думаю, все же существуют задачи и вне GUI. Но пока, соглашусь, сложно это представить.

 
Edgar Akhmadeev #:

Я использую кеширование, например, при вычислении HMAC SHA-256 ключа для REST-API, который вычисляется долго, а применяется несколько раз в минуту в случайные моменты.

Но функцию, имеющую точность 1 сек, и вызываемую многажды в секунду, я бы рассчитывал раз в секунду (т.е. контроль извне). Ваше решение - тоже вариант, но делать внутреннее кеширование в каждом подобном случае похоже на костыли.

где здесь костыльность?

bool TimeToStruct2100(datetime time, MqlDateTime& dt_struct) {
   static const int dm[13] = {0, -1, 30, 58, 89, 119, 150, 180, 211,242, 272, 303, 333};
   static int last_days = 0;
   static int last_result_m = 0;
   static int last_result_y = 0;
   static int last_result_yd = 0;
   static int last_result_d = 0;
   int days    = (int)(time / (60 * 60 * 24));
   if (last_days!=days) {
      last_days = days;
      last_result_y    = ((days << 2) + 2) / 1461;
      last_result_yd = days - ((last_result_y * 1461 + 1) >> 2);
      int isleap  = ((last_result_y & 3) == 2);
      int leapadj = ((last_result_yd < (59 + isleap)) ? 0 : (2 - isleap));
      last_result_m   = ((((last_result_yd + leapadj) * 12) + 373) / 367);
      last_result_d   = last_result_yd-dm[last_result_m] -((last_result_yd>59)?isleap:0);
   }
   dt_struct.year           = last_result_y+1970;
   dt_struct.mon            = last_result_m;
   dt_struct.day            = last_result_d;
   dt_struct.hour           = (int)((time / 3600) % 24);
   dt_struct.min            = (int)((time / 60) % 60);
   dt_struct.sec            = (int)(time % 60);
   dt_struct.day_of_week    = (days + 4) % 7;
   dt_struct.day_of_year    = last_result_yd;
   return (true);
}

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

 
Nikolai Semko #:
где здесь костыльность?

Я имею в виду, что реализовывать кеш придётся для каждого случая отдельно, где это применимо. Вместо того, чтобы не запускать расчёты, когда это не надо.

Не считаю, что кеш не полезная вещь. Файлы в ОС кешируются, и при частых операциях доступны очень быстро. Но в программе можно и нужно держать часто нужные данные в памяти, а не в файлах. Привёл как пример или аналогию.

Я уже сказал, что Ваш способ тоже применим. Но можно зайти с другой стороны.

 
Edgar Akhmadeev #:

Я имею в виду, что реализовывать кеш придётся для каждого случая отдельно, где это применимо. Вместо того, чтобы не запускать расчёты, когда это не надо.

Не считаю, что кеш не полезная вещь. Файлы в ОС кешируются, и при частых операциях доступны очень быстро. Но в программе можно и нужно держать часто нужные данные в памяти, а не в файлах. Привёл как пример или аналогию.

Я уже сказал, что Ваш способ тоже применим. Но можно зайти с другой стороны.

Не понял, про какую сторону идёт речь. Похоже, Вы не вникли в суть кода. В данном случае вычисления есть всегда, только часть из них, самая затратная, использует сохраненные значения в статических переменных, если входное время того же дня, что и предыдущее входное время.
 
Nikolai Semko #:
Не понял, про какую сторону идёт речь. Похоже, Вы не вникли в суть кода. В данном случае вычисления есть всегда, только часть из них, самая затратная, использует сохраненные значения в статических переменных, если входное время того же дня, что и предыдущее входное время.

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

Я говорю не о том, что расчёт идёт в тот же день, а о том, что Вы рассчитываете сотни раз в секунду, хотя результат имеет точность 1 секунду, и достаточно вызывать функцию раз в секунду (это и есть заход с другой стороны).

Я говорю не о том, что кеш раз в сутки не полезен, а о неудачном примере вызова функции многажды в секунду.

На этом откланиваюсь. Не люблю затянувшиеся дебаты и тем более холивары.
 
Edgar Akhmadeev #:

Я использую кеширование, например, при вычислении HMAC SHA-256 ключа для REST-API, который вычисляется долго, а применяется несколько раз в минуту в случайные моменты.

Но функцию, имеющую точность 1 сек, и вызываемую многажды в секунду, я бы рассчитывал раз в секунду (т.е. контроль извне). Ваше решение - тоже вариант, но делать внутреннее кеширование в каждом подобном случае похоже на костыли.

Edgar Akhmadeev #:

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

Я говорю не о том, что расчёт идёт в тот же день, а о том, что Вы рассчитываете сотни раз в секунду, хотя результат имеет точность 1 секунду, и достаточно вызывать функцию раз в секунду (это и есть заход с другой стороны).

Я говорю не о том, что кеш раз в сутки не полезен, а о неудачном примере вызова функции многажды в секунду.

На этом откланиваюсь. Не люблю затянувшиеся дебаты и тем более холивары.

Сложно понять о чем Вы говорите
Я не автор идеи, я лишь попытался убыстрить и расширить существующие функции. А, если речь про хеширование, то да. Это моя идея. 
Я вовсе не заводился.
Такое ощущение, что Вы почему-то думаете, что на вход данной функции подается текущее время, раз говорите о точности в 1 секунду. На вход данной функции подается разное не текущее время. Для демонстрации этого и записал анимационную гифку выше, в которой наглядно видно, что с помощью этой функции формируется нижнаяя шкала дата-время. Причем видно, что частота обращения к функции TimeToStruct2100() составляет сотни раз в секунду, чтобы сформировать временные шкалы разных масштабов. В случае хеширования эта функция в среднем работает быстрее примерно в два раза. 

Причина обращения: