Errores, fallos, preguntas - página 2500

 
Vict:

No se necesita alineación en absoluto, el procesador la necesita para no obtener algún int en dos líneas de caché.

no, la caché del procesador está cargada con prefetching de datos en absoluto, y los diferentes niveles de la caché están cargados con predicciones de transición en absoluto, pack() no puede llegar allí (a la caché) en absoluto, cualquieroperación aritmética (adición de 2 int) en lugar de ser ejecutada en 1 o 3 (hipotético) ciclos de reloj dará lugar a un análisis de alineación de datos, etc.

A nivel físico debería funcionar así: el compilador creó código ejecutable en él sí habrápack(), pero al cargar datos de la RAM sólo leerá datos int y el puntero del segmento de datos se moverá inmediatamente apack() byte (no int byte)


aunque puedo estar equivocado, ahora todos los procesos (incluido el propio procesador) están virtualizados y optimizados -este es mi razonamiento, ya que leí el libro sobre el Pentium-1 cuando estudié -.... era tan caro en su día ))))

 
Igor Makanu:

no, la caché del procesador está cargada con prefetching de datos en absoluto, y los diferentes niveles de la caché están cargados con predicciones de transición en absoluto, pack() no puede llegar allí (a la caché) en absoluto, cualquier operación aritmética (adición de 2 int) en lugar de ser ejecutada en 1 o 3 (hipotético) ciclos de reloj dará lugar a un análisis de alineación de datos, etc.

A nivel físico debería funcionar así: el compilador creó un código ejecutable en el que sí habrá pack(), pero cuando se carguen los datos de la RAM sólo se leerán los datos int y el puntero del segmento de datos se moverá inmediatamente albyte de pack() (no al byte int)

Bueno, yo no he dicho que el especificador pack() sea información de servicio para la CPU. Lo que quería decir es que todo este baile con la alineación en interés de la CPU y no del programador. Naturalmente, el compilador lo implementa insertando un espacio en blanco en las estructuras.

 
Alexey Viktorov:

Es decir, no hay ninguna alineación en MQL5.

Ha estado presente durante mucho tiempo.

 
Vict:

Estás cavando en el lugar equivocado, la alineación no es para ti en absoluto

Bueno, aunque un uso real que se me ocurre es en un entorno multihilo, para organizar los datos de manera que diferentes núcleos no escriban en la misma línea de caché, esto puede ralentizar mucho el rendimiento debido a la constante sincronización de la caché. Bueno, ahí también hay muchos matices, como el tipo de CPU.

 
fxsaber:

Ha estado presente durante mucho tiempo.

¿Recuerdas dónde se escribió?

 
fxsaber:

Entonces me temo que el punto de alineación se pierde

probado en bytes para ver qué hace la alineación:

#property strict

const uint FFFF=0xFFFFFFFF;
//+------------------------------------------------------------------+
struct A pack(4)
  {
   ushort            j;
  };
//+------------------------------------------------------------------+
struct B pack(8)
  {
   ushort            j;
  };
//+------------------------------------------------------------------+
union UnionCheckByte
  {
   uint              byte_2x4[2];
   A                 a;
   B                 b;
  };
//+------------------------------------------------------------------+
void OnStart()
  {
   UnionCheckByte tst;
   tst.byte_2x4[0]=FFFF;   tst.byte_2x4[1]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   Print("0xFFFFFFFF FFFFFFFF = ",tst.byte_2x4[0],",",tst.byte_2x4[1]);   // проверим
   
   
   
   tst.byte_2x4[0]=FFFF;   tst.byte_2x4[1]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   tst.a.j=0;
   Print("A.  = ",tst.byte_2x4[0],",",tst.byte_2x4[1]);   // проверим



   tst.byte_2x4[0]=FFFF;   tst.byte_2x4[1]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   tst.b.j=0;
   Print("B.  = ",tst.byte_2x4[0],",",tst.byte_2x4[1]);   // проверим
  }
//+------------------------------------------------------------------+

2019.07.07 17:51:30.601 tst (EURUSD,H1) 0xFFFFFF FFFFFFFF = 4294967295,4294967295

2019.07.07 17:51:30.601 tst (EURUSD,H1) A. = 4294901760,4294967295

2019.07.07 17:51:30.601 tst (EURUSD,H1) B. = 4294901760,4294967295




O no me he despertado todavía, o la alineación pack(4) / pack(8) no funciona, he especificado explícitamente los tamaños de las estructuras A y B al compilador


incluso así:

 ZeroMemory(tst.a);   //tst.a.j=0;
nada ha cambiado
 
Alexey Viktorov:

¿Recuerdas dónde se escribió?

No recuerdo si está en la documentación.

 
Igor Makanu:

trató de ver lo que hace la alineación en bytes:

O no estoy despierto todavía, o la alineación pack(4) / pack(8) no funciona, le dije inequívocamente al compilador los tamaños de las estructuras A y B

Así es como se inició esta discusión. Resulta que no es así.

Bueno, esta muestra es incorrecta después de todo. Al poner a cero el campo ushort, los bytes adicionales no tienen que cambiar en absoluto.


Lo más probable es que ZeroMemory se guíe por sizeof mientras que en ambos casos es dos por alguna razón propia.

 
fxsaber:

Así es como empezó esta discusión. Resulta que no es así en absoluto.

1. Bueno, este ejemplo es incorrecto después de todo. Al poner a cero el campo ushort, los bytes adicionales no tienen que ser cambiados en absoluto.


2. ZeroMemory debe guiarse por sizeof mientras que es doble en ambos casos por alguna razón.


1. sí estoy de acuerdo

2. ZeroMemory debería poner a cero la memoria por mí


No le veo sentido a pack() en MQL puro, a lo sumo se puede usar .dll para manipular los datos, pero debería funcionar seguro - eso es lo que dijeron los desarrolladores

 
Igor Makanu:

2. ZeroMemory es exactamente lo que necesito para restablecer la memoria

Lo hace.

struct A pack(4)
{
  short j;
  char i;
};

union U
{
  A a;
  uchar Bytes[sizeof(A)];
  
  U() { ArrayInitialize(this.Bytes, (char)0xFF); }
};

void OnStart()
{
  U u;
  
  ArrayPrint(u.Bytes); // 255 255 255 255
  
  ZeroMemory(u.a);
  ArrayPrint(u.Bytes); // 0 0 0 0
}