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

 
Renat Fatkhullin:


Код весь проверим внимательно. Интересно найти, в чем реальная причина.

Круто! Спасибо! Мне тоже интересно.

А sqrt, действительно, очень быстр. Меньше наносекунды :)). Фантастика!

 
Nikolai Semko:

Пробовал статический массив - тоже самое. 

Как бы sqrt не был бы быстр, но мне сложно поверить в то, что эта функция может быть в 10 раз быть быстрее простого чтения элемента массива.

На текущий момент множество старых оптимизационных техник уже не работают.


Причем, если в моем примере уменьшить размер канваса, скажем 50х50 ( для этого существует входной параметр Size, нужно вместо 0 установить 50), 

и массив будет значительно меньше (5000 элементов), то скоростная картина заметно меняется. Нет уже такого сильного контраста.

Но мне не понятно, разве от размера массива зависит скорость доступа к его элементам?

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

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

 
Renat Fatkhullin:


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

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

Я лишь вижу, что просто поменяв sqrt на простое чтение из массива, общая скорость расчета падает в 4 раза. А общая доля sqrt в этом достаточно большом расчете каждого пикселя вряд ли превышает 10%, а то и нескольких %.

Явная аномалия!

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

 
Nikolai Semko:

Я лишь вижу, что просто поменяв sqrt на простое чтение из массива, общая скорость расчета падает в 4 раза. А общая доля sqrt в этом достаточно большом расчете каждого пикселя вряд ли превышает 10%, а то и нескольких %.

Явная аномалия!

Я объяснил почему. Оптимизации математики девяностых годов уже не работают.

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

На таком уровне технической [не]чистоты я не буду обсуждать вопросы.

 
Renat Fatkhullin:

Я объяснил почему. Оптимизации математики девяностых годов уже не работают.

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

На таком уровне технической [не]чистоты я не буду обсуждать вопросы.

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

Где в этом изначальном коде замусоренность и оптимизация?

#include <Canvas\Canvas.mqh>

void OnStart()
  {
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CCanvas C;
   int Width=(ushort)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);                               // получаем Ширину окна
   int Height=(ushort)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);                             // получаем Высоту окна
   if(!C.CreateBitmapLabel(0,0,"CanvasExamlple",0,0,Width,Height,COLOR_FORMAT_XRGB_NOALPHA)) // создаем канвас размером текущего окна
   Print("Error creating canvas: ",GetLastError()); 
   uint i=0,j=100000;
   int size=Width*Height;
   uchar h[25600];
   for (int w=0;w<25600;w++) 
   h[w]= uchar(128+128*sin(double(w)/256));//создаем массив для ускорения работы
   double X1=0,Y1=0,X2=0,Y2=0,X3=0,Y3=0,X4=0,Y4=0;
   while(!IsStopped())
     {
      int pos=int(i%size);
      if(pos==0)
        {
         C.Update();
         //Sleep(30);
         X1= Width/2-(sin((double)j/100)*(double)Width/2);
         Y1= Height/2-(cos((double)j/140)*(double)Height/2);
         X2= Width/2+(cos((double)j/80)*(double)Width/2);
         Y2= Height/2+(sin((double)j/20)*(double)Height/2);
         X3= Width/2+(cos((double)j/85)*(double)Width/2);
         Y3= Height/2+(sin((double)j/65)*(double)Height/2);
         X4= Width/2+(cos((double)j/152)*(double)Width/2);
         Y4= Height/2+(sin((double)j/42)*(double)Height/2);
         j++;
        }
      int X=pos%Width;
      int Y=int(pos/Width);
      double D1=sqrt((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y));
      double D2=sqrt((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y));
      double D3=sqrt((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y));
      double D4=sqrt((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y));
      double d= (D1+D2)/(D1+D2+D3+D4);
      C.PixelSet(X,Y,XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]));
      i++;
     }
   C.Destroy();
  }

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

#include <Canvas\Canvas.mqh>
#property script_show_inputs 
input int N=8; // количество центов гравитации

void OnStart()
  {
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CCanvas C;
   int Width=(ushort)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);                               // get Window width
   int Height=(ushort)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);                             // get Window height 
   if(!C.CreateBitmapLabel(0,0,"CanvasExamlple",0,0,Width,Height,COLOR_FORMAT_XRGB_NOALPHA)) // create canvas with the size of the current window
      Print("Error creating canvas: ",GetLastError());
   uint i=0,j=100000;
   int size=Width*Height;
   uchar h[];
   ArrayResize(h,25600);
   for(int w=0;w<25600;w++) h[w]=uchar(128+128*sin(double(w)/256)); //create an array to speed up the work
                                                                  
   int k[]; ArrayResize(k,N*2);
   for(int w=0;w<N*2;w++) k[w]=20+rand()%200;
   double XP[],YP[],D[],D1[];
   ArrayResize(XP,N);
   ArrayResize(YP,N);
   ArrayResize(D,N);
   ArrayInitialize(XP,0);
   ArrayInitialize(YP,0);
  
   while(!IsStopped())
     {
      int pos=int(i%size);
      if(pos==0)
        {
         C.Update();
         for(int w=0;w<N;w++)
           {
            XP[w]= Width/2-(sin((double)j/k[2*w])*(double)Width/2);
            YP[w]= Height/2-(cos((double)j/k[2*w+1])*(double)Height/2);
           }
         j++;
        }
      int X=pos%Width;
      int Y=int(pos/Width);

      for(int w=0;w<N;w++) D[w]= sqrt((XP[w]-X)*(XP[w]-X)+(YP[w]-Y)*(YP[w]-Y));
      double S1=0,S2=0;
      for(int w=0;w<N/2;w++) S1+=D[w];
      for(int w=0;w<N;w++) S2+=D[w];
      double d=S1/S2;
      
      C.PixelSet(X,Y,XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]));
      i++;
     }
   C.Destroy();
  }
//+------------------------------------------------------------------+
 

Оптимизация математики: попытка использовать массивы вместо sqrt.

Вы не видите замусоренности и в этом корень непонимания правил тестирования производительности. Если тестируете precalculated array vs calculation, то нужно убрать все лишнее. Абсолютно все лишнее.

Утверждений вы сделали массу. Нужно уметь читать тексты со стороны получателя и очищая их от нерабочих защит автора.

 
Renat Fatkhullin:

Оптимизация математики: попытка использовать массивы вместо sqrt.

Да Бог с этим sqrt. Я уже понял, что в случае именно с этой функцией смысла в этом нет. Что плохого в попытке? Зато теперь я это знаю. 

И, кстати, в этом же примере использование массива h[] дает приличный выйгрыш в скорости вместо использования sin() .

Вопрос то уже в другом:

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

Вы не видите замусоренности и в этом корень непонимания правил тестирования производительности. Если тестируете precalculated array vs calculation, то нужно убрать все лишнее. Абсолютно все лишнее.

Вы знаете, Ренат, получить от Вас оплеуху совсем не стыдно, а даже можно счесть за честь. 

В моем понимании мусор - это что-то лишнее, что можно и нужно убрать. Но в данном случае там нечего убирать, иначе код перестанет работать.

Я не тестирую "precalculated array vs calculation", а анализирую скорость формирования кадра. 

Да и тестирования в моем случае никакого не требуется, потому как на моем слабом ноуте  и без тестирования видна разница между 25 кадрами в секунду и 6 кадрами в секунду. 

Утверждений вы сделали массу. Нужно уметь читать тексты со стороны получателя и очищая их от нерабочих защит автора.

Я лишь сделал пару предположений, но не утверждений:

- "Логично предположить, что считывание из массива SQRT[x] выполняется быстрее, чем функция sqrt(x)."

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

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

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

Могу даже поспорить. ))

 

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

Если же между обращениями есть какой-то код, то скорее всего будет промах кэша. Этим же объясняется разница в работе с большой и маленькой таблицей.

Кроме того существуют и другие неочевидные случаи. Поэтому тестировать надо окончательный неупрощённый вариант кода.

 
Ребят подскажите как в шаблонах функций определить что вызвана функция с типом enum ???
 
Vladimir Pastushak:
Ребят подскажите как в шаблонах функций определить что вызвана функция с типом enum ???
enum - это целочисленное перечисление.
0,1,2,3 ..., и т.д. ...
Причина обращения: