Errores, fallos, preguntas - página 2161

 
Renat Fatkhullin:


Revisemos todo el código con cuidado. Es interesante saber cuál es la verdadera razón.

¡Genial! Gracias. Yo también estoy interesado.

Y el sqrt es muy rápido. Menos de un nanosegundo :)). ¡Fantástico!

 
Nikolai Semko:

Probé con una matriz estática - lo mismo.

Por muy rápido que sea sqrt, me cuesta creer que esta función pueda ser 10 veces más rápida que la simple lectura de un elemento del array.

En este punto, muchas de las antiguas técnicas de optimización ya no funcionan.


Además, si en mi ejemplo para reducir el tamaño del lienzo, digamos 50x50 (para esto hay un parámetro de entrada Tamaño, es necesario establecer 50 en lugar de 0),

y la matriz será mucho más pequeña (5000 elementos), el panorama de la velocidad cambia significativamente. Ya no hay un contraste tan fuerte.

Pero lo que no entiendo es si el tamaño del array afecta a la velocidad de acceso a sus elementos.

No hay una prueba limpia de tus cálculos, estás haciendo suposiciones basadas en un código muy cargado.

Estás dejando de lado una tonelada de cálculos auxiliares que están en tu código y tienen un impacto significativo en los resultados.

 
Renat Fatkhullin:


No hay ninguna prueba limpia de tus cálculos, estás haciendo suposiciones basadas en un código muy desordenado.

Estás dejando de lado un montón de cálculos auxiliares que están en tu código y que tienen un impacto significativo en los resultados.

Todo lo que puedo ver es que sólo cambiando sqrt a una simple lectura de un array, la velocidad total de cálculo cae por un factor de 4. Y la proporción global de sqrt en este cálculo bastante grande de cada píxel apenas supera el 10%, o incluso unos pocos %.

¡Una clara anomalía!

Incluso cometí el error de decir que el tiempo de acceso a un elemento de la matriz es 10 veces el tiempo de sqrt. Mucho más dado que sqrt es tan rápido y la ralentización general es tan grande.

 
Nikolai Semko:

Sólo veo que cambiando sqrt por una simple lectura de un array, la velocidad total de cálculo se reduce en un factor de 4. Y la proporción global de sqrt en este cálculo bastante grande de cada píxel apenas supera el 10%, o incluso unos pocos %.

¡Una clara anomalía!

Ya he explicado por qué. Las optimizaciones de las matemáticas de los noventa ya no funcionan.

Pero tú sigues haciendo las siguientes afirmaciones basadas en el código real de la basura. En cuanto a las plantas, se equivocan.

A este nivel de [des]pureza técnica no voy a discutir los temas.

 
Renat Fatkhullin:

Ya he explicado por qué. Las optimizaciones de las matemáticas de los años noventa ya no funcionan.

Pero sigues haciendo las siguientes afirmaciones basándote en un código realmente basura. Es un error plausible.

A este nivel de [des]pureza técnica no voy a discutir los temas.

No entiendo a qué optimización matemática se refiere. Y no estaba haciendo ninguna afirmación, sólo me preguntaba cuál es el origen de los frenos.

¿Dónde está el desorden y la optimización en este código original?

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

Se puede utilizar este código más genérico, pero gracias al uso de bucles y matrices la velocidad de encuadre de la imagen se reduce casi a la mitad:

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

Optimización de las matemáticas: intentar usar arrays en lugar de sqrt.

No ves el desorden y esta es la raíz de tu incomprensión de las reglas de las pruebas de rendimiento. Si pruebas la matriz precalculada frente al cálculo, tienes que eliminar todo lo superfluo. Absolutamente todo es innecesario.

Has hecho muchas afirmaciones. Hay que saber leer los textos desde el lado del destinatario y limpiarlos de las defensas del autor que no funcionan.

 
Renat Fatkhullin:

Optimización de las matemáticas: intento de utilizar arrays en lugar de sqrt.

Oh, al diablo con el sqrt. Ya me he dado cuenta de que en el caso de esta función en particular, no tiene sentido. ¿Qué hay de malo en intentarlo? Pero ahora lo sé.

Por cierto, el uso de la matriz h[] en este ejemplo también proporciona una considerable ganancia de velocidad en lugar de utilizar sin().

La pregunta se refiere a otra cosa:

¿Por qué el uso del acceso a las celdas de una gran matriz aumenta el tiempo de cálculo varias veces cuando se esperaba que fuera sólo un poco?

No ves la camada y esa es la raíz de tu incomprensión de las normas de las pruebas de rendimiento.Si estás probando la matriz precalculada frente al cálculo, tienes que eliminar todo lo superfluo. Absolutamente todo es innecesario.

Sabes, Renat, no es una vergüenza recibir una bofetada tuya, sino incluso un honor.

A mi entender, la basura es algo innecesario que puede y debe ser eliminado. Pero en este caso no hay nada que limpiar, de lo contrario el código dejará de funcionar.

No estoy probando la"matriz precalculada frente al cálculo" sino analizando la velocidad de formación de la trama.

En mi caso no necesito ninguna prueba, porque tengo un portátil débil y puedo ver la diferencia entre 25 fps y 6 fps sin ninguna prueba.

Las afirmaciones que ha hecho son enormes. Hay que saber leer los textos desde el lado del destinatario y despejarlos de las defensas del autor que no funcionan.

Sólo he hecho un par de suposiciones, no afirmaciones:

- "Es lógico suponer que la lectura del array SQRT[x] es más rápida que la función sqrt(x)".

- "Uno podría suponer que el compilador está accediendo a un gran array de alguna manera extraña, y en cada vuelta de bucle parece "olvidarse" del array y hacer algún tipo de servicio de indexación cada vez. "

Pero aún así me atrevo a hacer esta afirmación porque aunque soy un programador autodidacta, pero autodidacta con gran experiencia y entiendo algo de los procesos dentro del procesador, porque hubo un tiempo en que mi programa favorito era Numega SoftIce, a través del cual escarbé en toneladas de código ajeno a nivel de ensamblador.

- Le aseguro que hay un error algorítmico en su compilador, relativo al acceso a los arrays, (quizás aparece sólo con arrays suficientemente grandes), que su equipo encontrará fácilmente, si pone vector de esfuerzo en esta dirección. Y mi ejemplo te ayudará.

Incluso podría argumentar. ))

 

Cuando se hace un bucle en una tabla, cada vez que se accede a ella, es probable que esté en la caché del procesador. Por ello, funciona más rápido.

Si hay algún código entre los accesos, es probable que haya una pérdida de caché. Esto también explica la diferencia en el manejo de una mesa grande y una pequeña.

Además, hay otros casos no evidentes. Por lo tanto, es necesario probar la versión final no simplificada del código.

 
Chicos, ¿cómo se puede saber en las plantillas de funciones que se ha llamado a una función con el tipo enum?
 
Vladimir Pastushak:
Chicos decidme como en las plantillas de funciones se determina que la función con tipo enum se llama???
enum es una enumeración de números enteros.
0,1,2,3 ..., etc...
Razón de la queja: