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

 
Nikolai Semko #:
Если поставить = rand() вместо 1, то  static  проигрывает.

Паритет.

Bench1(Tmp):5532 mcs.
Bench2(Tmp):5654 mcs.
 
fxsaber #:

Паритет.

template <typename T>
void Swap1( T &Value1, T &Value2 )
{
  const T Tmp = Value1;
  
  Value1 = Value2;
  Value2 = Tmp;
}

template <typename T>
void Swap2( T &Value1, T &Value2 )
{
  static T Tmp;
  
  Tmp = Value1;
  Value1 = Value2;
  Value2 = Tmp;
}

static выигрывает для простых типов и проигрывает для структур.

Файлы:
 
fxsaber #:

static выигрывает для простых типов и проигрывает для структур.

Крайне странный результат. ИМХО, но что-то не то у них получается. Ниже код, который g++ генерит. Либо у тебя тест некорректный, либо разработчики в компиляторе налажали. Ну не может Test1 потреблять больше процессорного времени чем Test2)

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


 
Vladimir Simakov #:

Либо у тебя тест некорректный, либо разработчики в компиляторе налажали. Ну не может Test1 потреблять больше процессорного времени чем Test2)

Я некомпетентен в этих вопросах. Не думаю, что уйдут в работу эти сообщения.
 
Vladimir Simakov #:

Крайне странный результат. ИМХО, но что-то не то у них получается. Ниже код, который g++ генерит.


MQL это не C++ ; разве что внешне похож...сравнивать с gcc не корректно

он вообще клонится в сторону C# 

PS/ ну а в примере: static проигрывает для структур, потому-что там(образно) ещё и деструктор. На всех вызовах кроме первого, то что было в static должно быть разрушено и/или вызван метод копирования

PPS/ (для желающих) можно экспериментировать с static T& или static T*, чтобы избежать ненужных копирований и деструкторов

 
Maxim Kuznetsov #:

MQL это не C++ ; разве что внешне похож...сравнивать с gcc не корректно

он вообще клонится в сторону C# 

PS/ ну а в примере: static проигрывает для структур, потому-что там(образно) ещё и деструктор. На всех вызовах кроме первого, то что было в static должно быть разрушено и/или вызван метод копирования

PPS/ (для желающих) можно экспериментировать с static T& или static T*, чтобы избежать ненужных копирований и деструкторов

Вот ни разу не соглашусь.

  1. Все, в конечном итоге сводится к машинному коду, который исполняется на процессоре.
  2. С# тут в принципе рядом не лежит. Ну ничего общего.
  3. Тривиальный деструктор не вызывается.
А теперь основное. Я показал, как ломается swap. Другого способа, как добиться того, что бы вариант со static storage duration выполнялся быстрее чем с local storage duration, я вот так, с ходу, не вижу. Так, что, если при оптимизации, действительно такое происходит, то это повод поправить.
 
Vladimir Simakov #:

Вот ни разу не соглашусь.

  1. Все, в конечном итоге сводится к машинному коду, который исполняется на процессоре.
  2. С# тут в принципе рядом не лежит. Ну ничего общего.
  3. Тривиальный деструктор не вызывается.
А теперь основное. Я показал, как ломается swap. Другого способа, как добиться того, что бы вариант со static storage duration выполнялся быстрее чем с local storage duration, я вот так, с ходу, не вижу. Так, что, если при оптимизации, действительно такое происходит, то это повод поправить.

про принципиально:  авторы языка педалируют "управляемый код". А это шарп, от которого впрочем, они-же ранее открещивались :-) 

Опять-же это не С++ и даже ни рядом. Ни вы ни я не можем сравнить итоговые маш.коды там и там и обосновать почему так и почему где-то верно/нет. Поэтому сравнения некорректны. У тебя ведь нет выхлопа asm от MQL? не с чем сравнивать

 
Vladimir Simakov #:

если при оптимизации, действительно такое происходит, то это повод поправить.

Накопилось таких поправить. Ilyas не зря хлеб ест. Уверен, работа идет.


Из недавних вопросов к оптимизации, что обнаружил.

 

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

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

Nikolai Semko, 2023.11.14 18:46

Любителям быстрых алгоритмов. Тем кто борется за наносекунды :)


Задача: Найти время открытия бара по заданному времени и ТФ, когда точно известно, что бар в это время существует. Например, по времени открытия и закрытия позиций. 

Большинство программистов воспользуется связкой iTime и iBarShift. Это будет самая медленная реализация, особенно такая реализация требует актуальной истории закаченных данных или вычесленных массивов. Более того, такой подход может выдавать ошибки при отсутсвии нужной истории.

Более продвинутые программисты решат эту задачу через структуру MqlDateTime и фукцию TimeToStruct(). Это не плохое решение и достаточно быстрое.

Но существует третье решение, которое более производительней предыдущего решения в несколько раз:

//+------------------------------------------------------------------+
// получает время открытия виртуального бара по входному времени и Таймфрейму, вне зависимости от того, существует реальный бар или нет.
// корректно считает только до 28.02.2100 !!!!
// не является заменой iBarShift!!! Не зависит от истории баров.  
datetime getStartTimeOfBarFast(ENUM_TIMEFRAMES tf, datetime t) {
   if (tf==0) tf=_Period;

   int ts=0;
   if (tf<PERIOD_MN1) {
      ushort i_tf= ushort(tf);
      uchar _i =uchar(i_tf>>14);
      int n = i_tf & 0x0FFF;
      ts = (_i==0)?n*60:(_i==1)?n*60*60:60*60*24*7;
   }
   if (tf<PERIOD_W1) return t-t%ts;
   if (tf==PERIOD_W1) return t-(t+4*24*60*60)%ts;
   else { // Period MN1
      static int dm[12] = {0,31,61,92,122,153,184, 214, 245, 275, 306, 337};
      static int last_days = 0;
      static datetime last_result = 0;
      int days = int(t/(24*60*60));
      if (last_days!=days) {
         last_days = days;
         int d1 = (days+306+365)%1461;
         int y = d1/365;
         datetime t1 = t - t%(24*60*60) - d1*24*60*60;
         int m = 0;
         if (d1==1460) {
            m=11;
            y--;
         };
         int d = d1-y*365+1;
         if (d!=31) if (d==276) m = 9;
            else m = int (d/30.68);
         if (m<0 || m>11) return -1;
         last_result = t1+y*365*24*60*60+dm[m]*24*60*60;
      }
      return last_result;
   }
}
//+------------------------------------------------------------------+

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

Альтернатива.

#define DAY (24 * 3600)

// Работает до конца XXI-века.
datetime GetMonthTime3( const int Year, const int Month )
{
  static const double Months[] = {0, 0.45, 31 * 1.01, 59 * 1.01, 90 * 1.007, 120 * 1.005, 151 * 1.004, 181 * 1.004,
                                  212 * 1.003, 243 * 1.003, 273 * 1.002, 304 * 1.002, 334 * 1.002};

  return((datetime)(((Year - 1970) * 365.25 + Months[Month]) * DAY) / DAY * DAY);
}
Алгоритмическая или реальная оптимизация?
Алгоритмическая или реальная оптимизация?
  • www.mql5.com
Для ускорения оптимизации ТС делают следующее Увеличивают количество параллельных вычислительных потоков. Пробуют разные компиляторы. Переписывают код под особенности железа (OpenCL, GPU и т.д.)
 

ну не совсем конечно алтернатива, так как это совсем другая задача. Год и месяц я расчитывал из даты, а здесь они подаются уже на вход. 
Моя реализация такой задачи без численных методов, а только логически, была бы, например, следующая:

datetime GetMonthTime4(const int Year, const int Month ) {
   static const int dm[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212 ,243, 273, 304, 334};
   return datetime(uint((Year-1970)*365+ (Year-1968)/4 - ((Year%4==0 && Month<3)?1:0) + dm[Month])*24*60*60);
}

не думаю, что разница в производительности будет существенной, тем более у меня отсутствуют типы double

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

char GetDayOfMonth(datetime time) {?}
Причина обращения: