Errores, fallos, preguntas - página 2505

 

un error de larga data en el editor:

- guardar el archivo con un nuevo nombre (por ejemplo: nombre_v1.2)
- colocar el cursor en alguna variable (o llamada a una función)
- pulsar alt+g

- se abre un archivo antiguo y la edición salta a él (

 
Vict:

En general, ni siquiera me lo esperaba:

El código es un poco sobrecomplicado - traté de llegar al elemento que no cabe en la línea de caché y martillarlo directamente, pero falló (probablemente habría tenido éxito si hubiera querido, pero me aburrí), y no cambié demasiado el código. Pero de esta manera es aún más impresionante - sólo uno de los 16 colapsos se realiza en un elemento que no cabe en la línea de caché, sin embargo tiene un resultado notable.

SZY: Más objetivamente en este caso para hacer RIGHT_ALIGNED a través de la inserción de dos cortos, y no mediante la eliminación de un solo (por lo que vamos a lograr dos actualizaciones de la línea de caché para ambos casos). El aumento de velocidad será más modesto, pero aún así se multiplicará por 1,5.

Disculpe, pero ¿dónde está el uso de la alineación? Este ejemplo no se trata de eso.

П. С. Publicar tu código sin comentarios y de forma burda es una falta de respeto a tus amigos.

 

Correctamente anotado, se agregó la alineación para usar objetos de estructura MQL en bibliotecas de terceros, en particular dotnet.

Fue cuando se añadieron las librerías dotnet para dar soporte a dotnet cuando se añadió la alineación a los campos de las estructuras/clases de los paquetes.

Para abreviar y simplificar, funciona así:

Para cada tipo (char, short, int, ...) hay una alineación por defecto (1, 2, 4 bytes respectivamente).
Para el campo de la estructura se elige el mínimo de dos alineaciones: la predeterminada y la definida por el usuario (mediante pack)

Al mismo tiempo, el tamaño del objeto empaquetado se establece de tal manera que el direccionamiento del campo del objeto en el array es siempre "correcto" (por defecto se establece un byte con el paquete).
Es por esto último por lo que se crea la falsa impresión de que el pack alinea el tamaño de la estructura; no es cierto, se alinean las direcciones de campo, lo que implica alinear el tamaño de la estructura.



Por ejemplo

struct A pack(8)
  {
   double d;
   char   c;
  };

void OnStart()
  {
   Print(sizeof(A));
   
  }

Resultado 16, para que el direccionamiento al primer campo d esté siempre alineado en 8 bytes

 
fxsaber:

Las carreras por mi cuenta no han mostrado ninguna diferencia notable.

He mejorado la idea original (no conté bien las direcciones en el primer código). Si no le importa, será interesante ver el resultado con usted.

#define  WRONG_ALIGNED
#define  CACHE_LINE_SIZE 64

struct Data {
#ifdef  WRONG_ALIGNED
   ushort pad;
#else
   uint pad;
#endif
   uint ar[CACHE_LINE_SIZE/sizeof(int)+1];
};

#import "msvcrt.dll"
  long memcpy(uint &, uint &, long);
#import
#define  getaddr(x) memcpy(x, x, 0)

void OnStart()
{
   Data data[32768];
   ZeroMemory(data);
   
   srand(GetTickCount());
   
   ulong start_time = GetMicrosecondCount();
   
   for(unsigned i = 0; i < 10000; ++ i) {
      int rndnum = rand();
      while (++rndnum < 32768) {
         int index = int(CACHE_LINE_SIZE - getaddr(data[rndnum].ar[0]) % CACHE_LINE_SIZE) / sizeof(int);
         ++ data[rndnum].ar[index];
         ++ data[rndnum].pad;
      }
   }
      
   Alert(GetMicrosecondCount() - start_time);
   
   Print(data[100].ar[0]);
   Print(data[100].pad);
}
/*
WRONG_ALIGNED:
6206397
6185472

RIGHT_ALIGNED
4089827
4003213
*/
En esencia sucede lo mismo con/sin WRONG_ALIGNED - en cada mientras escribimos en dos líneas de caché adyacentes (escribiendo en el pad siempre a la dirección correcta), la única diferencia es que con WRONG_ALIGNED hay casos (no siempre) en que una de las entradas en ar ocurre en uint, que no entrará completamente en la línea de caché, tengo una diferencia estable de unas 1,5 veces.
 
Vict:

He resuelto la idea original (en el primer código, no conté bien las direcciones). Si no le importa, será interesante ver el resultado en su caso.

Básicamente ocurre lo mismo con/sin WRONG_ALIGNED - en cada momento escribimos en dos líneas de caché adyacentes (la entrada de la almohadilla siempre a la dirección correcta), la única diferencia es que con WRONG_ALIGNED hay casos (no siempre) en los que una de las entradas en ar se produce en uint, que no llegará a toda la línea de caché, tengo una diferencia estable alrededor de 1,5 veces.

Por favor, explique, ¿qué está tratando de conseguir con esta línea? En el ejemplo anterior era un código basura.

int index = int(CACHE_LINE_SIZE - getaddr(data[rndnum].ar[0]) % CACHE_LINE_SIZE) / sizeof(int);
 
Francuz:

Por favor, explique lo que está tratando de conseguir con esta línea. En el ejemplo anterior era un código basura.

Encontrar nuestra posición en la línea de caché actual (la que tiene la almohadilla) y tomar tal índice para ar[], que el elemento con ella está en la siguiente línea de caché (tal vez el elemento está en dos líneas de caché con WRONG_ALIGNED)

 
Vict:

Encontrar nuestra posición en la línea de caché actual (aquella en la que está la almohadilla) y tomar un índice tal para ar[] que el elemento con ella esté en la siguiente línea de caché (quizás el elemento esté en dos líneas de caché en WRONG_ALIGNED)

Ahora estamos hablando de una compensación. Pero lo que usted muestra es un ejemplo puramente sintético, que nunca ocurrirá en la vida real. Y en ejemplos reales la ganancia de velocidad será de un 1% en el mejor de los casos. No deberías darle importancia a una aceleración tan insignificante.

П. С. Además, has calculado mal el tamaño del registro.
 
Francuz:

Ahora estamos hablando de desplazamiento. Pero lo que muestra es un ejemplo puramente sintético que nunca se encontrará en la vida real. En los ejemplos del mundo real, la ganancia de velocidad es de un 1% en el mejor de los casos. No deberías darle importancia a una aceleración tan insignificante.

No, este es un ejemplo bastante real. Sólo el 25% de las escrituras se producen en lugares "problemáticos" en la interfaz de las líneas de caché. ¿Cuánto es eso? Por ejemplo, si tienes un array doble largo, una línea de caché contiene sólo 4 valores y si no te molestas en alinear (y el compilador no lo hace por ti) entonces tendrás un 25% de lugares dobles problemáticos - como es en mi ejemplo. Hay muchos más matices que hablan a favor de la alineación, pero no voy a entrar en ellos, no estoy muy versado en el tema.

Bueno, señor de la casa.

P.D. Además, has calculado mal el tamaño del registro.
Realmente no lo conté para nada ))
 
Vict:

No, este es un ejemplo perfectamente realista. En él, sólo el 25% de las entradas se producen en lugares "problemáticos" en el cruce de líneas de la caché. ¿Es mucho? Por ejemplo, si tienes un array doble largo, una línea de caché contiene sólo 4 valores, y si no te importa la alineación (y el compilador no lo hace por ti), entonces obtienes un 25% de doble problemático - como en mi ejemplo. Hay muchos más matices, que hablan en favor de la alineación, pero no hablaré de ellos: no estoy suficientemente versado en el tema.

Bueno, tú eres el jefe.

Una vez más le digo que se confunde con el tamaño del registro.

 
Francuz:

Una vez más, estás confundiendo el tamaño del registro.

Justificar