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

 
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, я тоже беру в пользование ваш вариант.

 
Nikolai Semko #:

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

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

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

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

А если не объявлять в каждом цикле for новую int i, а использовать ту, что есть?

 
Alexey Viktorov #:

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

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

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

Выяснили же уже, что по быстродействию он проигрывает циклу for в классическом варианте.
 
Sergey Gridnev #:
Выяснили же уже, что по быстродействию он проигрывает циклу for в классическом варианте.

А я сначала пишу, а потом читаю.

Точней, я сначала ответил прочитав только то сообщение которое процитировал, а потом дочитал страницу до конца.

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

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