Errors, bugs, questions - page 2161

 
Renat Fatkhullin:


Let's check the whole code carefully. Interesting to find what the real reason is.

Cool! Thank you! I'm interested too.

And sqrt is very fast indeed. Less than a nanosecond :)). Fantastic!

 
Nikolai Semko:

Tried a static array - same thing.

As fast as sqrt is, I find it hard to believe that this function can be 10 times faster than just reading an array element.

At this point, a lot of the old optimization techniques no longer work.


Moreover, if in my example to reduce canvas size, say 50x50 (for this there is an input parameter Size, you need to set 50 instead of 0),

and the array will be much smaller (5000 elements), the speed picture changes significantly. There is no such a strong contrast anymore.

But what I don't understand is, does the array's size affect the speed of accessing its items?

There is no clean proof of your calculations, you are making assumptions based on very littered code.

You are neglecting a ton of auxiliary calculations that are in your code and have a significant impact on the results.

 
Renat Fatkhullin:


There is no clean proof of your calculations, you are making assumptions based on very messed up code.

You're neglecting a ton of auxiliary calculations that are in your code and have a significant impact on the results.

All I can see is that just by changing sqrt to a simple read from an array, the overall calculation speed drops by a factor of 4. And the overall proportion of sqrt in this rather large calculation of each pixel is hardly more than 10%, or even a few %.

A clear anomaly!

I even made the mistake of saying that the access time to an array element is 10 times the sqrt time. Much more given that sqrt is so fast and the overall slowdown is so great.

 
Nikolai Semko:

I can only see that by simply changing sqrt to a simple read from an array, the overall calculation speed drops by a factor of 4. And the overall proportion of sqrt in this rather large calculation of each pixel is hardly more than 10%, or even a few %.

A clear anomaly!

I have explained why. The optimizations of nineties mathematics no longer work.

But you keep making the following assertions based on real-life littered code. Plant-wise they are wrong.

At this level of technical [un]purity I will not discuss the issues.

 
Renat Fatkhullin:

I've explained why. The optimizations of the mathematics of the nineties no longer work.

But you keep making the following assertions based on really littered code. Plausibly flawed.

At this level of technical [un]purity I will not discuss the issues.

I don't understand what maths optimisation you are talking about. And I wasn't making any assertion, just wondering what is the source of the brakes.

Where is the clutter and optimisation in this original code?

#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();
  }

You can use this more generic code, but thanks to the use of loops and arrays the speed of image framing is almost halved:

#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();
  }
//+------------------------------------------------------------------+
 

Mathematical optimization: trying to use arrays instead of sqrt.

You don't see the clutter and this is the root of your misunderstanding of performance testing rules. If you test precalculated array vs calculation, you need to remove everything superfluous. Absolutely everything unnecessary.

You have made a lot of assertions. You need to be able to read the texts from the recipient's side and cleanse them of the author's non-working defences.

 
Renat Fatkhullin:

Optimising maths: trying to use arrays instead of sqrt.

Oh, hell with sqrt. I've already realised that in the case of this particular function, it doesn't make sense. What's wrong with trying? But now I know it.

By the way, using the h[] array in this sample also gives a considerable speed gain instead of using sin().

The question is about something else:

Why does use of access to cells of a large array increase calculation time by several times when it was expected only by a few percent?

You don't see the litter and that's the root of your misunderstanding of the performance testing rules.If you're testing precalculated array vs calculation, you need to remove everything superfluous. Absolutely everything unnecessary.

You know, Renat, it's not a shame to get a slap from you, but even an honour.

As I understand it, rubbish is something unnecessary that can and should be removed. But in this case there's nothing to clean up otherwise the code will stop working.

I am not testing"precalculated array vs calculation" but analyzing the speed of frame forming.

In my case I don't need any testing, because I have a weak laptop and can see the difference between 25 fps and 6 fps without any testing.

The assertions you have made are massive. You need to be able to read the texts from the recipient's side and clear them of the author's non-working defences.

I only made a couple of assumptions, not assertions:

- "It is logical to assume that reading from the array SQRT[x] is faster than the sqrt(x) function."

- "One might assume that the compiler is accessing a large array in some strange way, and at each loop turn it seems to "forget" about the array and do some sort of service indexing each time. "

But I still venture to make this statement because although I am a self-taught programmer, but self-taught with great experience and understand something about processes inside processor, because there was a time when my favorite program was Numega SoftIce, through which I dug through tons of alien code on assembler level.

- I assure you that there is an algorithmic bug in your compiler, concerning access to arrays, (perhaps it appears only with sufficiently large array), which your team will easily find, if you put vector of effort in this direction. And my example will help you.

I could even argue. ))

 

When you loop through a table, each time it is next accessed, it is likely to be in the processor's cache. This is why it runs faster.

If there is any code between accesses, there is likely to be a cache miss. This also explains the difference in handling a large and small table.

Besides, there are other non-obvious cases. Therefore it is necessary to test the final unsimplified version of the code.

 
Guys, how can you tell in function templates that a function with the enum type has been called?
 
Vladimir Pastushak:
Guys tell me how in the function templates to determine that the function with type enum is called???
enum is an integer enumeration.
0,1,2,3 ..., etc...
Reason: