Fehler, Irrtümer, Fragen - Seite 2500

 
Vict:

Sie graben an der falschen Stelle, denn Sie brauchen kein Alignment, der Prozessor braucht es nicht, um einen int auf zwei Cache-Zeilen zu bekommen.

nein, der Prozessor-Cache wird überhaupt mit Daten-Prefetching geladen, und die verschiedenen Cache-Ebenen werden überhaupt mit Übergangsvorhersagen geladen, pack() kann überhaupt nicht dorthin (in den Cache) gelangen, jedearithmetische Operation (Addition von 2 int), die nicht in 1 oder 3 (hypothetischen) Taktzyklen ausgeführt wird, führt zu einer Datenausrichtungsanalyse usw.

Auf einer physikalischen Ebene sollte es so funktionieren: der Compiler erstellt ausführbaren Code in ihm ja gibt espack(), aber beim Laden von Daten aus dem RAM wird es nur lesen int Daten und die Daten-Segment-Zeiger wird sofort aufpack() Byte (nicht int Byte)verschoben werden


obwohl ich vielleicht falsch liege, sind jetzt alle Prozesse (einschließlich des Prozessors selbst) virtualisiert und optimiert - das ist meine Schlussfolgerung, da ich das Buch über den Pentium-1 gelesen habe, als ich studierte -.... es war damals so teuer ))))

 
Igor Makanu:

nein, der Prozessor-Cache wird überhaupt mit Daten-Prefetching geladen, und die verschiedenen Cache-Ebenen werden überhaupt mit Übergangsvorhersagen geladen, pack() kann überhaupt nicht dorthin (in den Cache) gelangen, jede arithmetische Operation (Addition von 2 int), die nicht in 1 oder 3 (hypothetischen) Taktzyklen ausgeführt wird, führt zu einer Datenausrichtungsanalyse usw.

Auf der physikalischen Ebene sollte es so funktionieren: Compiler erstellt ausführbaren Code in ihm ja es wirdpack(), aber beim Laden von Daten aus dem RAM nur Lesen int Daten getan werden und Daten-Segment-Zeiger wird sofort aufpack() Byte (nicht auf int Byte)verschoben werden

Nun, ich habe nicht gesagt, dass der pack()-Spezifizierer eine Service-Information für die CPU ist. Was ich meinte, war dieser ganze Tanz mit der Ausrichtung im Interesse der CPU und nicht des Programmierers. Natürlich wird dies vom Compiler durch das Einfügen eines Leerzeichens in Strukturen umgesetzt.

 
Alexey Viktorov:

Das heißt, in MQL5 gibt es überhaupt keine Ausrichtung.

Sie ist schon seit langem vorhanden.

 
Vict:

Sie graben an der falschen Stelle, Alignment ist nichts für Sie

Eine reale Anwendung, an die ich denken kann, ist in einer Multi-Thread-Umgebung, um Daten so anzuordnen, dass verschiedene Kerne nicht in dieselbe Cache-Zeile schreiben, was die Leistung wegen der ständigen Cache-Synchronisierung wirklich verlangsamen kann. Nun, auch hier gibt es viele Nuancen, wie den CPU-Typ.

 
fxsaber:

Sie ist schon seit langem vorhanden.

Erinnern Sie sich, wo darüber geschrieben wurde?

 
fxsaber:

Ich fürchte, dann ist der Sinn der Angleichung verloren gegangen.

in Bytes versucht, um zu sehen, was die Ausrichtung bewirkt:

#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) 0xFFFFFFFFFFF 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




Entweder bin ich noch nicht aufgewacht, oder das pack(4) / pack(8) Alignment funktioniert nicht, ich habe dem Compiler explizit die Größen der Strukturen A und B angegeben


trotzdem:

 ZeroMemory(tst.a);   //tst.a.j=0;
hat sich nichts geändert
 
Alexey Viktorov:

Erinnern Sie sich, wo das geschrieben wurde?

Ich weiß nicht mehr, ob es in der Dokumentation steht.

 
Igor Makanu:

versucht zu sehen, was die Ausrichtung in Bytes bewirkt:

Entweder bin ich noch nicht wach, oder die pack(4)/pack(8)-Ausrichtung funktioniert nicht, ich habe dem Compiler die Größen der Strukturen A und B eindeutig mitgeteilt

Auf diese Weise wurde diese Diskussion in Gang gesetzt. Es stellte sich heraus, dass dies nicht der Fall ist.

Nun, diese Probe ist also doch falsch. Beim Nullsetzen des ushort-Feldes müssen die zusätzlichen Bytes nicht verändert werden.


ZeroMemory richtet sich höchstwahrscheinlich nach sizeof, während es in beiden Fällen aus irgendeinem Grund zwei ist.

 
fxsaber:

So begann also diese Diskussion. Es hat sich herausgestellt, dass das überhaupt nicht der Fall ist.

1. Dieses Beispiel ist also doch falsch. Durch das Nullsetzen des ushort-Feldes müssen die zusätzlichen Bytes nicht verändert werden.


2) ZeroMemory muss sich an sizeof orientieren, während es aus irgendeinem Grund in beiden Fällen doppelt ist.


1. ja, ich stimme zu

2 ZeroMemory sollte den Speicher für mich auf Null setzen


Ich sehe keinen Sinn in pack() in reinem MQL, höchstens können Sie .dll verwenden, um Daten zu manipulieren, aber es sollte sicher funktionieren - das ist, was die Entwickler gesagt haben

 
Igor Makanu:

2. ZeroMemory ist genau das, was ich brauche, um den Speicher zurückzusetzen

Das tut sie.

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
}