Fehler, Irrtümer, Fragen - Seite 2161

 
Renat Fatkhullin:


Lassen Sie uns den gesamten Code sorgfältig prüfen. Es wäre interessant zu erfahren, was der wahre Grund dafür ist.

Super! Ich danke Ihnen! Ich bin auch daran interessiert.

Und sqrt ist in der Tat sehr schnell. Weniger als eine Nanosekunde :)). Fantastisch!

 
Nikolai Semko:

Ich habe es mit einem statischen Array versucht - dasselbe Ergebnis.

So schnell wie sqrt ist, fällt es mir schwer zu glauben, dass diese Funktion 10-mal schneller sein kann als das einfache Lesen eines Array-Elements.

An diesem Punkt funktionieren viele der alten Optimierungstechniken nicht mehr.


Außerdem, wenn in meinem Beispiel, um die Größe der Leinwand zu reduzieren, sagen wir 50x50 (für diese gibt es einen Eingabeparameter Größe, müssen Sie 50 anstelle von 0 zu setzen),

und das Array viel kleiner ist (5000 Elemente), ändert sich das Geschwindigkeitsbild erheblich. Es gibt keinen so starken Kontrast mehr.

Aber was ich nicht verstehe, ist, ob die Größe des Arrays die Geschwindigkeit des Zugriffs auf seine Elemente beeinflusst?

Es gibt keinen sauberen Beweis für Ihre Berechnungen, Sie machen Annahmen auf der Grundlage von sehr verunreinigtem Code.

Sie vernachlässigen eine ganze Reihe von Hilfsberechnungen, die in Ihrem Code enthalten sind und einen erheblichen Einfluss auf die Ergebnisse haben.

 
Renat Fatkhullin:


Es gibt keinen sauberen Beweis für Ihre Berechnungen, Sie machen Annahmen, die auf einem sehr verkorksten Code basieren.

Sie vernachlässigen eine ganze Reihe von Hilfsberechnungen, die in Ihrem Code enthalten sind und einen erheblichen Einfluss auf die Ergebnisse haben.

Alles, was ich sehen kann, ist, dass allein durch die Änderung von sqrt auf ein einfaches Lesen aus einem Array, die Gesamtberechnungsgeschwindigkeit um den Faktor 4 sinkt. Und der Gesamtanteil von sqrt an dieser recht umfangreichen Berechnung jedes Pixels beträgt kaum mehr als 10 % oder sogar nur ein paar %.

Eine klare Anomalie!

Ich habe sogar den Fehler gemacht, zu sagen, dass die Zugriffszeit auf ein Array-Element das 10-fache der sqrt-Zeit ist. Viel mehr, da sqrt so schnell ist und die allgemeine Verlangsamung so groß ist.

 
Nikolai Semko:

Ich kann nur feststellen, dass durch die einfache Änderung von sqrt in ein einfaches Lesen aus einem Array die Gesamtberechnungsgeschwindigkeit um den Faktor 4 sinkt. Und der Gesamtanteil von sqrt an dieser recht umfangreichen Berechnung jedes Pixels beträgt kaum mehr als 10 % oder sogar nur ein paar %.

Eine klare Anomalie!

Ich habe erklärt, warum. Die Optimierungen der Mathematik der neunziger Jahre funktionieren nicht mehr.

Aber Sie stellen immer wieder die folgenden Behauptungen auf der Grundlage von realem, verschmutztem Code auf. In Bezug auf die Pflanzen sind sie falsch.

Auf dieser Ebene der technischen [Un]reinheit werde ich nicht auf die Fragen eingehen.

 
Renat Fatkhullin:

Ich habe erklärt, warum. Die Optimierungen der Mathematik aus den neunziger Jahren funktionieren nicht mehr.

Aber Sie stellen immer wieder die folgenden Behauptungen auf der Grundlage von wirklich verunreinigtem Code auf. Plausibel fehlerhaft.

Auf dieser Ebene der technischen [Un]reinheit werde ich nicht auf die Fragen eingehen.

Ich verstehe nicht, von welcher mathematischen Optimierung Sie sprechen. Und ich habe keine Behauptungen aufgestellt, sondern mich nur gefragt, woher die Bremsen kommen.

Wo ist das Durcheinander und die Optimierung in diesem ursprünglichen 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();
  }

Sie können diesen allgemeineren Code verwenden, aber dank der Verwendung von Schleifen und Arrays wird die Geschwindigkeit des Bildaufbaus fast halbiert:

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

Optimierung der Mathematik: Versuch der Verwendung von Arrays anstelle von sqrt.

Sie sehen das Durcheinander nicht, und das ist die Ursache für Ihr Missverständnis der Regeln für Leistungstests. Wenn Sie ein vorberechnetes Array gegen eine Berechnung testen, müssen Sie alles Überflüssige entfernen. Alles absolut unnötig.

Sie haben eine Reihe von Behauptungen aufgestellt. Sie müssen in der Lage sein, die Texte von der Empfängerseite her zu lesen und sie von den nicht funktionierenden Abwehrmechanismen des Autors zu befreien.

 
Renat Fatkhullin:

Optimierung der Mathematik: Versuch der Verwendung von Arrays anstelle von sqrt.

Ach, zum Teufel mit sqrt. Ich habe bereits festgestellt, dass dies im Falle dieser speziellen Funktion keinen Sinn macht. Was ist falsch daran, es zu versuchen? Aber jetzt weiß ich es.

Übrigens bringt die Verwendung des h[]-Arrays in diesem Beispiel auch einen erheblichen Geschwindigkeitsgewinn gegenüber der Verwendung von sin().

Die Frage bezieht sich auf etwas anderes:

Warum erhöht sich die Rechenzeit durch den Zugriff auf die Zellen eines großen Arrays um ein Vielfaches, obwohl nur ein paar Prozent erwartet wurden?

Sie sehen den Wurf nicht, und das ist die Ursache für Ihr Missverständnis der Regeln für Leistungstests.Wenn Sie ein vorberechnetes Array gegen eine Berechnung testen, müssen Sie alles Überflüssige entfernen. Alles absolut unnötig.

Weißt du, Renat, es ist keine Schande, von dir eine Ohrfeige zu bekommen, sondern sogar eine Ehre.

Nach meinem Verständnis ist Müll etwas Unnötiges, das entfernt werden kann und sollte. Aber in diesem speziellen Fall gibt es nichts zu bereinigen, sonst würde der Code nicht mehr funktionieren.

Ich teste nicht"vorberechnetes Array vs. Berechnung", sondern analysiere die Geschwindigkeit der Rahmenbildung.

In meinem Fall brauche ich keine Tests, denn ich habe einen schwachen Laptop und kann den Unterschied zwischen 25 fps und 6 fps ohne Tests erkennen.

Die Behauptungen, die Sie aufgestellt haben, sind massiv. Sie müssen in der Lage sein, die Texte von der Empfängerseite her zu lesen und sie von den nicht funktionierenden Abwehrmechanismen des Autors zu befreien.

Ich habe nur ein paar Annahmen gemacht, keine Behauptungen:

- "Es ist logisch anzunehmen, dass das Lesen aus dem Array SQRT[x] schneller ist als die Funktion sqrt(x)."

-Man könnte annehmen, dass der Compiler auf eine seltsame Weise auf ein großes Array zugreift, und bei jeder Schleifenumdrehung scheint er das Array zu "vergessen" und jedes Mal eine Art von Dienstindexierung vorzunehmen. "

Aber ich wage diese Aussage trotzdem, weil ich zwar ein autodidaktischer Programmierer bin, aber ein Autodidakt mit großer Erfahrung und etwas Verständnis für die Vorgänge im Prozessor, denn es gab eine Zeit, in der mein Lieblingsprogramm Numega SoftIce war, mit dem ich mich durch Tonnen von fremdem Code auf Assembler-Ebene gegraben habe.

- Ich versichere Ihnen, dass es einen algorithmischen Fehler in Ihrem Compiler gibt, der den Zugriff auf Arrays betrifft (vielleicht taucht er nur bei ausreichend großen Arrays auf), den Ihr Team leicht finden wird, wenn Sie einen Vektor der Bemühungen in diese Richtung setzen. Und mein Beispiel wird Ihnen helfen.

Ich könnte sogar argumentieren. ))

 

Wenn Sie eine Tabelle in einer Schleife durchlaufen, befindet sie sich bei jedem nächsten Zugriff wahrscheinlich im Cache des Prozessors. Aus diesem Grund läuft es schneller.

Liegt zwischen den Zugriffen ein beliebiger Code, so liegt wahrscheinlich ein Cache-Miss vor. Dies erklärt auch den Unterschied in der Handhabung eines großen und eines kleinen Tisches.

Außerdem gibt es andere, nicht offensichtliche Fälle. Daher ist es notwendig, die endgültige, nicht vereinfachte Version des Codes zu testen.

 
Leute, wie kann man in Funktionsvorlagen erkennen, dass eine Funktion mit dem Typ enum aufgerufen wurde?
 
Vladimir Pastushak:
Leute, sagt mir, wie man in den Funktionsvorlagen feststellt, dass die Funktion mit dem Typ enum aufgerufen wird?
enum ist eine ganzzahlige Aufzählung.
0,1,2,3 ..., usw...