Errori, bug, domande - pagina 2161

 
Renat Fatkhullin:


Controlliamo attentamente l'intero codice. È interessante scoprire quale sia la vera ragione.

Fico! Grazie! Anch'io sono interessato.

E sqrt è davvero molto veloce. Meno di un nanosecondo :)). Fantastico!

 
Nikolai Semko:

Ho provato con un array statico - stessa cosa.

Per quanto sqrt sia veloce, trovo difficile credere che questa funzione possa essere 10 volte più veloce della semplice lettura di un elemento dell'array.

A questo punto, molte delle vecchie tecniche di ottimizzazione non funzionano più.


Inoltre, se nel mio esempio per ridurre la dimensione della tela, diciamo 50x50 (per questo c'è un parametro di input Size, è necessario impostare 50 invece di 0),

e l'array sarà molto più piccolo (5000 elementi), il quadro della velocità cambia significativamente. Non c'è più un contrasto così forte.

Ma quello che non capisco è: la dimensione dell'array influenza la velocità di accesso ai suoi elementi?

Non c'è nessuna prova pulita dei vostri calcoli, state facendo delle ipotesi basate su un codice molto litigioso.

Stai trascurando una tonnellata di calcoli ausiliari che sono nel tuo codice e hanno un impatto significativo sui risultati.

 
Renat Fatkhullin:


Non c'è nessuna prova pulita dei vostri calcoli, state facendo ipotesi basate su un codice molto incasinato.

Stai trascurando una tonnellata di calcoli ausiliari che sono nel tuo codice e hanno un impatto significativo sui risultati.

Tutto quello che posso vedere è che solo cambiando sqrt con una semplice lettura da un array, la velocità di calcolo complessiva scende di un fattore 4. E la proporzione complessiva di sqrt in questo calcolo piuttosto grande di ogni pixel è appena superiore al 10%, o addirittura a qualche %.

Una chiara anomalia!

Ho anche fatto l'errore di dire che il tempo di accesso a un elemento dell'array è 10 volte il tempo sqrt. Molto di più visto che sqrt è così veloce e il rallentamento generale è così grande.

 
Nikolai Semko:

Posso solo vedere che cambiando semplicemente sqrt con una semplice lettura da un array, la velocità di calcolo complessiva scende di un fattore 4. E la proporzione complessiva di sqrt in questo calcolo piuttosto grande di ogni pixel è appena superiore al 10%, o addirittura a qualche %.

Una chiara anomalia!

Ho spiegato il perché. Le ottimizzazioni della matematica degli anni novanta non funzionano più.

Ma voi continuate a fare le seguenti affermazioni basate su codice reale disseminato. Sul piano vegetale si sbagliano.

A questo livello di [dis]purezza tecnica non discuterò le questioni.

 
Renat Fatkhullin:

Ho spiegato il perché. Le ottimizzazioni della matematica degli anni novanta non funzionano più.

Ma voi continuate a fare le seguenti affermazioni basate su un codice davvero litigioso. Plausibilmente difettoso.

A questo livello di [dis]purezza tecnica non discuterò le questioni.

Non capisco di quale ottimizzazione matematica stia parlando. E non stavo facendo alcuna affermazione, mi stavo solo chiedendo qual è la fonte dei freni.

Dov'è il disordine e l'ottimizzazione in questo codice originale?

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

È possibile utilizzare questo codice più generico, ma grazie all'uso di loop e array la velocità di inquadratura dell'immagine è quasi dimezzata:

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

Ottimizzazione matematica: provare a usare gli array invece di sqrt.

Non vedete il disordine e questa è la radice del vostro fraintendimento delle regole del performance testing. Se testate l'array precalcolato rispetto al calcolo, dovete rimuovere tutto il superfluo. Assolutamente tutto ciò che non è necessario.

Lei ha fatto molte affermazioni. Bisogna saper leggere i testi dalla parte del destinatario e ripulirli dalle difese non funzionanti dell'autore.

 
Renat Fatkhullin:

Ottimizzare la matematica: provare a usare gli array invece di sqrt.

Oh, al diavolo sqrt. Ho già capito che nel caso di questa particolare funzione non ha senso. Cosa c'è di male nel provare? Ma ora lo so.

A proposito, usare l'array h[] in questo esempio dà anche un notevole guadagno di velocità invece di usare sin().

La domanda riguarda un'altra cosa:

Perché l'uso dell'accesso alle celle di una grande matrice aumenta il tempo di calcolo di parecchie volte quando ci si aspettava solo qualche punto percentuale?

Tu non vedi la spazzatura e questa è la radice del tuo fraintendimento delle regole del test delle prestazioni.Se stai testando l'array precalcolato rispetto al calcolo, devi rimuovere tutto il superfluo. Assolutamente tutto ciò che non è necessario.

Sai, Renat, non è una vergogna ricevere uno schiaffo da te, ma addirittura un onore.

Per come la vedo io, la spazzatura è qualcosa di inutile che può e deve essere rimosso. Ma in questo caso non c'è niente da pulire, altrimenti il codice smetterà di funzionare.

Non sto testando"array precalcolato vs calcolo", ma analizzando la velocità di formazione dei frame.

Nel mio caso non ho bisogno di alcun test, perché ho un portatile debole e posso vedere la differenza tra 25 fps e 6 fps senza alcun test.

Le affermazioni che avete fatto sono enormi. Bisogna saper leggere i testi dalla parte del destinatario e liberarli dalle difese non funzionanti dell'autore.

Ho fatto solo un paio di supposizioni, non affermazioni:

- "È logico supporre che la lettura dall'array SQRT[x] sia più veloce della funzione sqrt(x)".

-"Si potrebbe supporre che il compilatore stia accedendo ad un grande array in qualche modo strano, e ad ogni giro di loop sembra "dimenticare" l'array e fare ogni volta una sorta di indicizzazione di servizio. "

Ma mi azzardo ancora a fare questa affermazione perché anche se sono un programmatore autodidatta, ma autodidatta con grande esperienza e capisco qualcosa dei processi all'interno del processore, perché c'è stato un tempo in cui il mio programma preferito era Numega SoftIce, attraverso il quale ho scavato attraverso tonnellate di codice alieno a livello assembler.

- Vi assicuro che c'è un bug algoritmico nel vostro compilatore, riguardante l'accesso agli array, (forse appare solo con array sufficientemente grandi), che il vostro team troverà facilmente, se mettete vettori di sforzo in questa direzione. E il mio esempio vi aiuterà.

Potrei anche argomentare. ))

 

Quando si esegue il loop di una tabella, ogni volta che si accede ad essa, è probabile che sia nella cache del processore. Questo è il motivo per cui funziona più velocemente.

Se c'è del codice tra gli accessi, è probabile che ci sia un cache miss. Questo spiega anche la differenza nella gestione di un tavolo grande e piccolo.

Inoltre, ci sono altri casi non ovvi. Quindi è necessario testare la versione finale non semplificata del codice.

 
Ragazzi, come potete dire nei modelli di funzione che una funzione con il tipo enum è stata chiamata?
 
Vladimir Pastushak:
Ragazzi, ditemi come nei modelli di funzione per determinare che la funzione con tipo enum è chiamata?
enum è un'enumerazione di interi.
0,1,2,3 ..., ecc.