Doppelte Ausrichtung

8

Nach der Diskussion von diesem Beitrag habe ich verstanden, dass der Hauptgrund dafür Die Ausrichtung der Strukturelemente ist Leistung (und einige Einschränkungen der Architektur).

Wenn wir Microsoft (Visual C ++), Borland / CodeGear (C ++ - Builder), Digital Mars (DMC) und GNU (GCC) beim Kompilieren für 32-Bit x86 untersuchen: Die Ausrichtung für int ist 4 Bytes und Wenn int nicht ausgerichtet ist, kann es vorkommen, dass 2 Zeilen Speicherbänke gelesen werden.

Meine Frage ist warum nicht double zu 4 Bytes ausgerichtet werden soll? 4 byte aligned double verursacht auch 2 Reihen von Speicherbänken, die lesen ....

Zum Beispiel wird im folgenden Beispiel double auf 8 ausgerichtet, die tatsächliche Größe der Struktur ist sizeof(char) + (alignment for double padding) + sizeof(int) = 20 bytes .

%Vor%

Danke

    
Yakov 19.06.2012, 19:50
quelle

4 Antworten

9

Ein erweiterter Kommentar:

Laut GCC-Dokumentation über -malign-double :

  

Die Ausrichtung von double Variablen auf einer Zwei-Wort-Grenze erzeugt Code, der auf einem Pentium auf Kosten von mehr Speicher etwas schneller läuft.

     

Bei x86-64 ist -malign-double standardmäßig aktiviert.

     

Warnung: Wenn Sie den Schalter -malign-double verwenden, werden Strukturen, die die obigen Typen enthalten, anders ausgerichtet als die veröffentlichten binären Schnittstellenspezifikationen für die 386 und sind nicht binärkompatibel mit Strukturen in Code, die ohne diese Option kompiliert wurden.

Ein Wort bedeutet hier i386 Wort, das 32 Bits ist.

Windows verwendet 64-Bit-Ausrichtung von double -Werten auch im 32-Bit-Modus, während SysV i386 ABI-konforme Unices 32-Bit-Ausrichtung verwenden. Die 32-Bit-Windows-API Win32 stammt von Windows NT 3.1, das im Gegensatz zu Windows-Versionen der aktuellen Generation Intel i386, Alpha, MIPS und sogar den obskuren Intel i860 zum Ziel hat. Da native RISC-Systeme wie Alpha und MIPS erfordern, dass double -Werte 64-Bit-ausgerichtet sind (andernfalls tritt ein Hardwarefehler auf), könnte die Portabilität der Grund für die 64-Bit-Ausrichtung im Win32 i386 ABI gewesen sein.

64-Bit-x86-Systeme, die auch als AMD64 oder x86-64 oder x64 bekannt sind, erfordern, dass double -Werte 64-Bit-ausgerichtet sind, andernfalls tritt ein Fehlausrichtungsfehler auf und die Hardware führt eine teure "Korrektur" durch verlangsamt den Speicherzugriff. Deshalb sind double -Werte in allen modernen x86-64 ABIs (SysV und Win32) 64-Bit-ausgerichtet.

    
Hristo Iliev 19.06.2012, 22:15
quelle
6

Die meisten Compiler passen Datenwerte automatisch an die Wortgröße der Plattform oder an die Größe des Datentyps an, je nachdem, welcher Wert kleiner ist. Die überwiegende Mehrheit der Consumer- und Enterprise-Prozessoren verwendet eine 32-Bit-Wortgröße. (Selbst 64-Bit-Systeme verwenden normalerweise 32 Bit als native Wortgröße)

Als solches könnte die Reihenfolge der Mitglieder in Ihrer Struktur möglicherweise etwas Speicher verschwenden. In Ihrem speziellen Fall geht es Ihnen gut. Ich füge den tatsächlichen Footprint des verwendeten Speichers Kommentare hinzu:

%Vor%

Diese Regel gilt auch für Strukturen. Selbst wenn Sie sie so neu angeordnet haben, dass das kleinste Feld zuletzt war, haben Sie immer noch eine Struktur derselben Größe (16 Byte).

%Vor%

Wenn Sie mehr Felder deklarieren würden, die kleiner als 4 Byte sind, könnten Sie Speicherreduzierungen sehen, wenn Sie sie nach Größe gruppieren. Zum Beispiel:

%Vor%

Das Deklarieren einer dummen Struktur könnte viel Speicher verschwenden, es sei denn, der Compiler ordnet Ihre Elemente neu (was im Allgemeinen nicht der Fall ist, ohne explizit dazu aufgefordert zu werden)

%Vor%

Doppel sind größer als 32 Bit und sind daher gemäß der Regel im ersten Abschnitt 32 Bit ausgerichtet. Jemand erwähnte eine Compiler-Option, die die Ausrichtung ändert, und dass die Standard-Compiler-Option zwischen 32- und 64-Bit-Systemen unterschiedlich ist, dies gilt auch. Die wirkliche Antwort auf Doubles ist, dass es von der Plattform und dem Compiler abhängt.

Die Speicherleistung wird durch Wörter bestimmt: Das Laden aus dem Speicher erfolgt in Phasen, die von der Platzierung der Daten abhängen. Wenn die Daten ein Wort umfassen (d. H. Wort ist ausgerichtet), muss nur dieses Wort geladen werden. Wenn es nicht korrekt ausgerichtet ist (d. H. Ein int bei 0x2), muss der Prozessor 2 Wörter laden, um seinen Wert korrekt zu lesen. Das gleiche gilt für Doppeleinträge, die normalerweise 2 Wörter benötigen, aber bei Fehlausrichtung 3. 3. Auf 64-Bit-Systemen, bei denen ein natives Laden von 64-Bit-Größen möglich ist, verhalten sie sich bei richtig ausgerichteten 32-Bit-Einträgen auf 32-Bit-Systemen Sie können mit einer Ladung abgerufen werden, ansonsten benötigen sie 2.

    
Wug 19.06.2012 20:16
quelle
2

Zunächst ist es die Architektur, die die Ausrichtungsanforderung auferlegt, einige werden die nicht ausgerichteten Speicherzugriffe tolerieren, andere werden es nicht tun.

Nehmen wir als Beispiel die Plattform x86-32bit windows, in dieser Plattform ist die Ausrichtungsanforderung für int und long jeweils 4 bytes und 8 bytes .

Es ist klar, warum int Alignment-Anforderung ist 4 bytes , einfach, so dass die CPU alles nur durch einen Zugriff lesen kann.

Der Grund, warum die Ausrichtungsanforderung für doulbe 8 bytes und nicht 4 bytes ist, liegt daran, dass, wenn es 4 bytes war, dann darüber nachdenken würde, was passieren würde, wenn diese Doppelung an der Adresse 60 und der Cache-Zeilengröße war 64bits , in diesem Fall muss der Prozessor 2 Cache-Zeilen vom Speicher in den Cache laden, aber wenn dieser double ausgerichtet war, wird dies nicht passieren, da in diesem Fall double immer Teil ist einer Cache-Zeile und nicht zwischen zwei geteilt.

%Vor%     
AlexDan 30.03.2014 16:42
quelle
0

Die Frage ist in Bezug auf die CPU-Architektur sehr plattformspezifisch. Zum Beispiel in Architekturen, die eine Strafe für den Betrieb an nicht-4-Byte-ausgerichteten Adressen geben, kann das Ausrichten Ihrer Variablen (tatsächlich ihre Adressen) auf 4 Bytes eine solche Strafe vermeiden.

Compiler sind ziemlich gut mit solchen Dingen, besonders wenn Sie ihnen die Ziel-CPU-Architektur liefern, für die sie optimieren können, damit sie das meiste für Sie tun können, und viele andere Optimierungen. Sehen Sie sich zum Beispiel das -march -Flag von GCC an, mit dem Sie auf CPU-Architekturen zielen können.

    
zxcdw 19.06.2012 19:57
quelle

Tags und Links