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

fxsaber #:

Пример из жизни MQL5 EA.

да, для массива пример рабочий

Nikolai Semko #:

в любом цикле всегда минимум одна проверка

Вот самый короткий способ полного перебора типа uchar:

Работает, спасибо.

Nikolai Semko #:

да, для массива пример рабочий

Там несколько тоньше.

ulong HistoryDealGetTicket( int ) { return(0); } // Перегрузка в каком-нибудь далеком mqh.

void OnStart()
{      
  if (HistorySelect(0, INT_MAX))
  {
    for (uint i = HistoryDealsTotal(); (bool)i--; ) // Хорошо - потенциальная перегрузка не сломает результат.
      Print(HistoryDealGetTicket(i));
      
    for (int i = HistoryDealsTotal() - 1; i >= 0; i--) // Классика - плохо из-за потенциальной перегрузки.
      Print(HistoryDealGetTicket(i));
  }
}
fxsaber #:

Перебор всех сделок.

Кстати классный вариант для перебора значений всего ненулевого массива. Возможно - лучший по производительности(не уверен)
Спасибо, взял на заметку.

Nikolai Semko #:

Возможно - лучший по производительности(не уверен)

Помнится производительность рекурсии, как цикла, была очень удивительна. 

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

Индикаторы: MaFromMa

Ilyas, 2019.04.04 14:59

Да, тут есть над чем поработать

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


Для скорости (более лучших оптимизаций компилятором)  работы программы в циклах, старайтесь избегать использования (адресации к) глобальных переменных и членов объектов.


Попробуйте в приведённом примере использовать локальную sum1 вместо глобальной


Nikolai Semko #:
Это нормальное поведение с целочисленными типами и называется оно переполнение. У uchar 255+1 = 0; 0-1  = 255.
 Ведь не существует в uchar чисел меньше 0 и больше 255.
Каждый программист должен знать об этом и учитывать в своих алгоритмах.
 0A программистов продукт решили сделать,
Один спросил "А деньги где?", и их осталось 9.

9 программистов предстали перед боссом,
Один из них не знал FoxPro, и их осталось 8.

8 программистов купили IBM,
Один сказал "Мак лучше!", и их осталось 7.

7 программистов хотели help прочесть,
У одного накрылся винт, и их осталось 6.

6 программистов пытались код понять,
Один из них сошел с ума, и их осталось 5.

5 программистов купили CD-ROM,
Один принес китайский диск - остались вчетвером.

4 программиста работали на Си,
Один из них хвалил Паскаль, и их осталось 3.

3 программиста в сети играли в DOOM,
Один чуть-чуть замешкался, и счет стал равен двум.

2 программиста набрали дружно: "win"
Один устал загрузки ждать - остался лишь 1.

1 программист все взял под свой контроль,
Hо встретился с заказчиком, и их осталось 0.

0 программистов ругал сердитый шeф,
Потом уволил одного, и стало их FF. 
Nikolai Semko #:

Помнится производительность рекурсии, как цикла, была очень удивительна. 

С рекурсией, действительно, тогда было удивительное. Что касается массивов через unsigned-индексы, то там будет странно увидеть разность в скорости.

fxsaber #:

С рекурсией, действительно, тогда было удивительное. Что касается массивов через unsigned-индексы, то там будет странно увидеть разность в скорости.

Надо проверить ради интереса. Хотя, согласен - маловероятно 
Nikolai Semko #:
Надо проверить ради интереса. Хотя, согласен - маловероятно 

проверил. Результаты неожиданные для меня. Вариант с bool() работает на ~75%(!!!) медленнее. Видимо преобразование типов (даже bool) весьма затратная штука. Помнится, об этом несколько раз говорил Ренат.

2023.07.19 16:22:18.164 TestLoopsPerformance (USDJPY,M1)        ========================
2023.07.19 16:22:18.164 TestLoopsPerformance (USDJPY,M1)        время выполнения = 338 , контрольная сумма = 423652232; цикл while
2023.07.19 16:22:18.164 TestLoopsPerformance (USDJPY,M1)        время выполнения = 488 , контрольная сумма = 423652232; цикл for(int i = size-1;i>=0;i--)
2023.07.19 16:22:18.164 TestLoopsPerformance (USDJPY,M1)        время выполнения = 836 , контрольная сумма = 423652232; цикл for(int i = size;(bool)i--;)
2023.07.19 16:22:18.164 TestLoopsPerformance (USDJPY,M1)        время выполнения = 493 , контрольная сумма = 423652232; цикл do while
2023.07.19 16:22:18.164 TestLoopsPerformance (USDJPY,M1)        время выполнения = 351 , контрольная сумма = 423652232; цикл через рекурсию
2023.07.19 16:22:21.937 TestLoopsPerformance (USDJPY,M1)        ========================
2023.07.19 16:22:21.937 TestLoopsPerformance (USDJPY,M1)        время выполнения = 338 , контрольная сумма = 3813875620; цикл while
2023.07.19 16:22:21.937 TestLoopsPerformance (USDJPY,M1)        время выполнения = 482 , контрольная сумма = 3813875620; цикл for(int i = size-1;i>=0;i--)
2023.07.19 16:22:21.937 TestLoopsPerformance (USDJPY,M1)        время выполнения = 833 , контрольная сумма = 3813875620; цикл for(int i = size;(bool)i--;)
2023.07.19 16:22:21.937 TestLoopsPerformance (USDJPY,M1)        время выполнения = 491 , контрольная сумма = 3813875620; цикл do while
2023.07.19 16:22:21.937 TestLoopsPerformance (USDJPY,M1)        время выполнения = 347 , контрольная сумма = 3813875620; цикл через рекурсию
2023.07.19 16:22:24.799 TestLoopsPerformance (USDJPY,M1)        ========================
2023.07.19 16:22:24.799 TestLoopsPerformance (USDJPY,M1)        время выполнения = 335 , контрольная сумма = 499067232; цикл while
2023.07.19 16:22:24.799 TestLoopsPerformance (USDJPY,M1)        время выполнения = 482 , контрольная сумма = 499067232; цикл for(int i = size-1;i>=0;i--)
2023.07.19 16:22:24.799 TestLoopsPerformance (USDJPY,M1)        время выполнения = 833 , контрольная сумма = 499067232; цикл for(int i = size;(bool)i--;)
2023.07.19 16:22:24.799 TestLoopsPerformance (USDJPY,M1)        время выполнения = 486 , контрольная сумма = 499067232; цикл do while
2023.07.19 16:22:24.799 TestLoopsPerformance (USDJPY,M1)        время выполнения = 341 , контрольная сумма = 499067232; цикл через рекурсию

рекурсия с циклом while сейчас почти одинаковые и самые быстрые. Значит Ильяс починил.

цикл for на ~35% медленнее, чем while, и почти одинаков по производительности do while


Вывод: для максимальной производительности используйте цикл while!


#define size 1000000
#define total_tests 500
//+------------------------------------------------------------------+
void OnStart() {
   uint sum1=0,sum2=0, sum3=0, sum4=0, sum5=0;
   ulong t1=0, t2=0, t3=0, t4=0, t5=0;
   uint i;
   uint X[];
   ArrayResize(X,size);
   for(i=0; i<size; i++) X[i]=rand();
   
   for (int j = 0; j++<total_tests;) {
      ulong t=GetMicrosecondCount();
      i=0;
      while(i<size) sum1+=X[i++];
      t1+=GetMicrosecondCount()-t;

      t=GetMicrosecondCount();
      for(int i = size-1; i>=0; i--) sum4+=X[i];
      t4+=GetMicrosecondCount()-t;

      t=GetMicrosecondCount();
      for(int i = size; (bool)i--;) sum3+=X[i];
      t3+=GetMicrosecondCount()-t;

      t=GetMicrosecondCount();
      i=size-1;
      do sum5+=X[i];
      while(i--!=0);
      t5+=GetMicrosecondCount()-t;

      t=GetMicrosecondCount();
      i=0;
      Recursion(X,sum2,i);
      t2+=GetMicrosecondCount()-t;
   }

   Print("========================");
   Print("время выполнения = "+string(t1/total_tests)+" , контрольная сумма = "+string(sum1) + "; цикл while");
   Print("время выполнения = "+string(t4/total_tests)+" , контрольная сумма = "+string(sum4) + "; цикл for(int i = size-1;i>=0;i--)");
   Print("время выполнения = "+string(t3/total_tests)+" , контрольная сумма = "+string(sum3) + "; цикл for(int i = size;(bool)i--;)");
   Print("время выполнения = "+string(t5/total_tests)+" , контрольная сумма = "+string(sum5) + "; цикл do while");
   Print("время выполнения = "+string(t2/total_tests)+" , контрольная сумма = "+string(sum2) + "; цикл через рекурсию");
}
//+------------------------------------------------------------------+
void Recursion(uint &X[],uint &sum, uint &i) {
   sum+=X[i];
   i++;
   if(i<size) Recursion(X,sum,i);
}
//+------------------------------------------------------------------+

Файлы:
Nikolai Semko #:

Кстати классный вариант для перебора значений всего ненулевого массива. Возможно - лучший по производительности(не уверен)
Спасибо, взял на заметку.

Да, мне тоже очень понравился такой вариант.

Раньше я пользовался таким

  for(i = OrdersTotal(); i--; i > 0)

Спасибо fxsaber, я тоже беру в пользование ваш вариант.