Erreurs, bugs, questions - page 2500

 
Igor Makanu:

non, le cache du processeur n'est pas du tout chargé avec la préextraction des données, et les différents niveaux de cache sont chargés avec les prédictions de transition, pack() ne peut pas du tout y arriver (dans le cache), toute opération arithmétique (addition de 2 int) au lieu d'être exécutée sur 1 ou 3 cycles d'horloge (hypothétique) entraînera une analyse de l'alignement des données, etc.

Au niveau physique, cela devrait fonctionner comme suit : le compilateur a créé un code exécutable dans lequel oui il y aurapack(), mais lors du chargement des données depuis la RAM, il ne lira que des données int et le pointeur du segment de données sera immédiatement déplacé vers l'octet pack() (et non vers l'octet int).

Je n'ai pas dit que le spécificateur pack() est une information de service pour le CPU. Ce que je voulais dire, c'est que toute cette danse avec l'alignement est dans l'intérêt du CPU et non du programmeur. Naturellement, elle est implémentée par le compilateur en insérant un blanc dans les structures.

 
Alexey Viktorov:

C'est-à-dire qu'il n'y a pas d'alignement du tout dans MQL5.

Elle est présente depuis longtemps.

 
Vict:

Vous creusez au mauvais endroit, l'alignement n'est pas du tout pour vous.

Bien que je puisse penser à une utilisation réelle dans un environnement multithread, pour organiser les données de sorte que les différents cœurs n'écrivent pas sur la même ligne de cache, cela peut vraiment ralentir les performances en raison de la synchronisation constante du cache. Eh bien, il y a beaucoup de nuances là aussi, comme le type de CPU.

 
fxsaber:

Elle est présente depuis longtemps.

Vous vous rappelez où il a été écrit ?

 
fxsaber:

Alors j'ai peur que le but de l'alignement soit perdu.

essayé en octets pour voir ce que l'alignement fait :

#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) 0xFFFFFFFFFF FFFFFFFFFF = 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




Soit je ne me suis pas encore réveillé, soit l'alignement pack(4) / pack(8) ne fonctionne pas, j'ai explicitement spécifié les tailles des structures A et B au compilateur


quand même :

 ZeroMemory(tst.a);   //tst.a.j=0;
rien n'a changé
 
Alexey Viktorov:

Vous rappelez-vous où il a été écrit ?

Je ne me souviens pas si c'est dans la documentation.

 
Igor Makanu:

a essayé de voir ce que l'alignement fait en octets :

soit je ne me suis pas encore réveillé, soit l'alignement pack(4) / pack(8) ne fonctionne pas, j'ai indiqué sans ambiguïté au compilateur les tailles des structures A et B

C'est ainsi que cette discussion a été lancée. Il s'est avéré que ce n'est pas le cas.

Eh bien, cet échantillon est incorrect après tout. Lors de la mise à zéro du champ ushort, les octets supplémentaires ne doivent pas être modifiés du tout.


ZeroMemory est très probablement guidé par sizeof alors qu'il est de deux dans les deux cas pour une raison qui lui est propre.

 
fxsaber:

C'est ainsi que cette discussion a commencé. Il s'avère que ce n'est pas du tout comme ça.

1. Finalement, cet exemple est incorrect. En mettant à zéro le champ ushort, les octets supplémentaires n'ont pas à être modifiés du tout.


2. ZeroMemory doit être guidé par sizeof alors qu'il est double dans les deux cas pour une raison quelconque.


1. oui, je suis d'accord

2. ZeroMemory devrait simplement remettre la mémoire à zéro pour moi.


je ne vois pas l'intérêt de pack() en MQL pur, tout au plus peut-on utiliser des .dll pour manipuler les données, mais cela devrait fonctionner à coup sûr - c'est ce qu'ont dit les développeurs

 
Igor Makanu:

2. ZeroMemory est exactement ce dont j'ai besoin pour réinitialiser la mémoire.

C'est le cas.

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
}
 
fxsaber:

C'est ce qui se passe.

Je l'ai essayé comme ça :

const uint FFFF=0xFFFFFFFF;
//+------------------------------------------------------------------+
struct A pack(4)
  {
   ushort            j1;
   ushort            j2;
  };
//+------------------------------------------------------------------+
struct B pack(8)
  {
   ushort            j1;
   ushort            j2;
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
union UnionCheckByte
  {
   uint              byte_4x4[4];
   A                 a;
   B                 b;
  };
//+------------------------------------------------------------------+
void OnStart()
  {
   UnionCheckByte tst;
   tst.byte_4x4[0]=FFFF;   tst.byte_4x4[1]=FFFF;   tst.byte_4x4[2]=FFFF;   tst.byte_4x4[3]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   ArrayPrint(tst.byte_4x4);
// A   
   Print("A:");
   tst.byte_4x4[0]=FFFF;   tst.byte_4x4[1]=FFFF;   tst.byte_4x4[2]=FFFF;   tst.byte_4x4[3]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   A zeroA;
   ZeroMemory(zeroA);
   tst.a = zeroA;
   ArrayPrint(tst.byte_4x4);
   
// B
   Print("B:");
   tst.byte_4x4[0]=FFFF;   tst.byte_4x4[1]=FFFF;   tst.byte_4x4[2]=FFFF;   tst.byte_4x4[3]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   B zeroB;
   ZeroMemory(zeroB);
   tst.b = zeroB;
   ArrayPrint(tst.byte_4x4);
 
   Print("sizeof(A) = ",sizeof(A)," , sizeof(B) = ",sizeof(B));
  }
//+------------------------------------------------------------------+

2019.07.07 18:31:02.708 tst (EURUSD,H1) 4294967295 4294967295 4294967295 4294967295 4294967295

2019.07.07 18:31:02.708 tst (EURUSD,H1) A

2019.07.07 18:31:02.708 tst (EURUSD,H1) 0 4294967295 4294967295 4294967295 4294967295

2019.07.07 18:31:02.708 tst (EURUSD,H1) B

2019.07.07 18:31:02.708 tst (EURUSD,H1) 0 4294967295 4294967295 4294967295 4294967295

2019.07.07 18:31:02.708 tst (EURUSD,H1) sizeof(A) = 4 , sizeof(B) = 4


nous ne mettons toujours à zéro que les 4 premiers octets.

Raison: