Zugegeben, ich verstehe es nicht. Angenommen, Sie haben einen Speicher mit einem Speicherwort mit einer Länge von 1 Byte. Warum können Sie nicht auf eine 4 Byte lange Variable in einem einzelnen Speicherzugriff auf eine nicht ausgerichtete Adresse zugreifen (dh nicht durch 4 teilbar), wie dies bei ausgerichteten Adressen der Fall ist?
195
Antworten:
Dies ist eine Einschränkung vieler zugrunde liegender Prozessoren. Es kann normalerweise umgangen werden, indem 4 ineffiziente Einzelbyte-Abrufe anstelle eines effizienten Wortabrufs durchgeführt werden. Viele Sprachspezifizierer entschieden jedoch, dass es einfacher ist, sie nur zu verbieten und die Ausrichtung zu erzwingen.
Dieser Link enthält viel mehr Informationen , die das OP entdeckt hat.
quelle
Das Speichersubsystem eines modernen Prozessors ist auf den Zugriff auf Speicher mit der Granularität und Ausrichtung seiner Wortgröße beschränkt. Dies ist aus mehreren Gründen der Fall.
Geschwindigkeit
Moderne Prozessoren verfügen über mehrere Ebenen des Cache-Speichers, durch die Daten gezogen werden müssen. Das Unterstützen von Einzelbyte-Lesevorgängen würde den Durchsatz des Speichersubsystems eng an den Durchsatz der Ausführungseinheit binden (auch bekannt als CPU-gebunden). Dies alles erinnert daran, wie der PIO-Modus von DMA aus vielen der gleichen Gründe auf Festplatten übertroffen wurde .
Die CPU liest immer mit ihrer Wortgröße (4 Byte auf einem 32-Bit-Prozessor). Wenn Sie also einen nicht ausgerichteten Adresszugriff durchführen - auf einem Prozessor, der dies unterstützt -, liest der Prozessor mehrere Wörter. Die CPU liest jedes Speicherwort, das Ihre angeforderte Adresse überspannt. Dies bewirkt eine bis zu zweifache Verstärkung der Anzahl von Speichertransaktionen, die für den Zugriff auf die angeforderten Daten erforderlich sind.
Aus diesem Grund kann es sehr leicht langsamer sein, zwei Bytes als vier zu lesen. Angenommen, Sie haben eine Struktur im Speicher, die folgendermaßen aussieht:
Auf einem 32-Bit-Prozessor würde es höchstwahrscheinlich wie hier gezeigt ausgerichtet sein:
Der Prozessor kann jedes dieser Mitglieder in einer Transaktion lesen.
Angenommen, Sie hatten eine gepackte Version der Struktur, möglicherweise aus dem Netzwerk, in dem sie aus Gründen der Übertragungseffizienz gepackt wurde. es könnte ungefähr so aussehen:
Das Lesen des ersten Bytes wird dasselbe sein.
Wenn Sie den Prozessor bitten, Ihnen 16 Bit von 0x0005 zu geben, muss er ein Wort von 0x0004 lesen und 1 Byte nach links verschieben, um es in ein 16-Bit-Register zu legen. etwas zusätzliche Arbeit, aber die meisten können das in einem Zyklus erledigen.
Wenn Sie von 0x0001 nach 32 Bit fragen, erhalten Sie eine 2-fache Verstärkung. Der Prozessor liest von 0x0000 in das Ergebnisregister und verschiebt 1 Byte nach links, liest dann erneut von 0x0004 in ein temporäres Register, verschiebt 3 Byte nach rechts und dann
OR
mit dem Ergebnisregister.Angebot
Wenn die Architektur für einen bestimmten Adressraum davon ausgehen kann, dass die 2 LSBs immer 0 sind (z. B. 32-Bit-Maschinen), kann sie auf viermal mehr Speicher zugreifen (die zwei gespeicherten Bits können vier verschiedene Zustände darstellen) oder auf dieselbe Menge Speicher mit 2 Bits für so etwas wie Flags. Wenn Sie die 2 LSBs von einer Adresse entfernen, erhalten Sie eine 4-Byte-Ausrichtung. wird auch als Schritt von 4 Bytes bezeichnet. Jedes Mal, wenn eine Adresse inkrementiert wird, wird Bit 2 und nicht Bit 0 effektiv inkrementiert, dh die letzten 2 Bits bleiben immer bestehen
00
.Dies kann sich sogar auf das physische Design des Systems auswirken. Wenn der Adressbus 2 weniger Bits benötigt, können 2 weniger Pins auf der CPU und 2 weniger Spuren auf der Leiterplatte vorhanden sein.
Atomizität
Die CPU kann atomar mit einem ausgerichteten Speicherwort arbeiten, was bedeutet, dass kein anderer Befehl diesen Vorgang unterbrechen kann. Dies ist entscheidend für den korrekten Betrieb vieler sperrenfreier Datenstrukturen und anderer Parallelitätsparadigmen .
Fazit
Das Speichersystem eines Prozessors ist wesentlich komplexer und komplizierter als hier beschrieben; Eine Diskussion darüber, wie ein x86-Prozessor tatsächlich den Speicher adressiert, kann helfen (viele Prozessoren arbeiten ähnlich).
Die Einhaltung der Speicherausrichtung bietet noch viele weitere Vorteile, die Sie in diesem IBM Artikel lesen können .
Die Hauptverwendung eines Computers besteht darin, Daten zu transformieren. Moderne Speicherarchitekturen und -technologien wurden über Jahrzehnte hinweg optimiert, um das Ein- und Auslesen von mehr Daten zwischen mehr und schnelleren Ausführungseinheiten auf äußerst zuverlässige Weise zu ermöglichen.
Bonus: Caches
Eine andere Ausrichtung für die Leistung, auf die ich zuvor hingewiesen habe, ist die Ausrichtung auf Cache-Zeilen, die (zum Beispiel auf einigen CPUs) 64B sind.
Weitere Informationen darüber, wie viel Leistung durch die Nutzung von Caches erzielt werden kann, finden Sie in der Galerie der Prozessor-Cache-Effekte . von dieser Frage auf Cache-Zeilengrößen
quelle
Sie können mit einigen Prozessoren ( das Nehalem kann dies tun ), aber zuvor war der gesamte Speicherzugriff auf einer 64-Bit- (oder 32-Bit-) Leitung ausgerichtet, da der Bus 64 Bit breit ist, mussten Sie jeweils 64 Bit abrufen und es war wesentlich einfacher, diese in ausgerichteten "Blöcken" von 64 Bit abzurufen.
Wenn Sie also ein einzelnes Byte erhalten möchten, haben Sie den 64-Bit-Block abgerufen und dann die nicht gewünschten Bits maskiert. Einfach und schnell, wenn sich Ihr Byte am richtigen Ende befand, aber wenn es sich in der Mitte dieses 64-Bit-Blocks befand, müssten Sie die unerwünschten Bits maskieren und die Daten dann an die richtige Stelle verschieben. Schlimmer noch, wenn Sie eine 2-Byte-Variable wollten, die jedoch auf 2 Blöcke aufgeteilt war, erforderte dies das Doppelte der erforderlichen Speicherzugriffe.
Da jeder der Meinung ist, dass Speicher billig ist, hat er den Compiler dazu gebracht, die Daten an den Blockgrößen des Prozessors auszurichten, damit Ihr Code auf Kosten des verschwendeten Speichers schneller und effizienter ausgeführt wird.
quelle
Grundsätzlich liegt der Grund darin, dass der Speicherbus eine bestimmte Länge hat, die viel, viel kleiner als die Speichergröße ist.
Die CPU liest also aus dem On-Chip-L1-Cache aus, der heutzutage häufig 32 KB beträgt. Der Speicherbus, der den L1-Cache mit der CPU verbindet, hat jedoch die erheblich geringere Breite der Cache-Zeilengröße. Dies liegt in der Größenordnung von 128 Bit .
So:
Falsch ausgerichtete Zugriffe überlappen gelegentlich zwei Cache-Zeilen, und dies erfordert einen völlig neuen Cache-Lesevorgang, um die Daten zu erhalten. Es könnte sogar bis zum DRAM fehlen.
Darüber hinaus muss ein Teil der CPU auf dem Kopf stehen, um aus diesen beiden unterschiedlichen Cache-Zeilen, die jeweils einen Teil der Daten enthalten, ein einzelnes Objekt zusammenzusetzen. In einer Zeile befinden sich die Bits sehr hoher Ordnung, in der anderen die Bits sehr niedriger Ordnung.
Es wird dedizierte Hardware geben, die vollständig in die Pipeline integriert ist und das Verschieben ausgerichteter Objekte auf die erforderlichen Bits des CPU-Datenbusses handhabt. Bei falsch ausgerichteten Objekten fehlt diese Hardware jedoch möglicherweise, da es wahrscheinlich sinnvoller ist, diese Transistoren zur Beschleunigung der korrekten Optimierung zu verwenden Programme.
In jedem Fall würde der zweite Speicherlesevorgang, der manchmal erforderlich ist, die Pipeline verlangsamen, unabhängig davon, wie viel Spezialhardware (hypothetisch und dumm) für das Patchen falsch ausgerichteter Speicheroperationen vorgesehen war.
quelle
@joshperry hat diese Frage hervorragend beantwortet. Zusätzlich zu seiner Antwort habe ich einige Zahlen, die die beschriebenen Effekte grafisch darstellen, insbesondere die 2X-Verstärkung. Hier ist ein Link zu einer Google-Tabelle, der zeigt, wie sich unterschiedliche Wortausrichtungen auswirken. Außerdem ist hier ein Link zu einem Github-Kern mit dem Code für den Test. Der Testcode wurde aus dem Artikel von Jonathan Rentzsch übernommen, auf den @joshperry verwies. Die Tests wurden auf einem Macbook Pro mit einem Quad-Core-Intel Core i7 64-Bit-Prozessor mit 2,8 GHz und 16 GB RAM durchgeführt.
quelle
x
undy
koordinieren?Wenn ein System mit byteadressierbarem Speicher über einen 32 Bit breiten Speicherbus verfügt, bedeutet dies, dass effektiv vier byteweite Speichersysteme vorhanden sind, die alle zum Lesen oder Schreiben derselben Adresse verdrahtet sind. Für einen ausgerichteten 32-Bit-Lesevorgang sind Informationen erforderlich, die in allen vier Speichersystemen unter derselben Adresse gespeichert sind, sodass alle Systeme gleichzeitig Daten liefern können. Ein nicht ausgerichteter 32-Bit-Lesevorgang würde erfordern, dass einige Speichersysteme Daten von einer Adresse und einige Daten von der nächsthöheren Adresse zurückgeben. Obwohl es einige Speichersysteme gibt, die so optimiert sind, dass sie solche Anforderungen erfüllen können (zusätzlich zu ihrer Adresse haben sie effektiv ein "Plus Eins" -Signal, wodurch sie eine Adresse verwenden, die höher als angegeben ist), verursacht eine solche Funktion erhebliche Kosten und Komplexität eines Speichersystems;
quelle
Wenn Sie einen 32-Bit-Datenbus haben, beginnen die mit dem Speicher verbundenen Adressbus-Adressleitungen bei A 2 , sodass in einem einzigen Buszyklus nur auf 32-Bit-ausgerichtete Adressen zugegriffen werden kann.
Wenn also ein Wort eine Adressausrichtungsgrenze überspannt - dh A 0 für 16/32-Bit-Daten oder A 1 für 32-Bit-Daten nicht Null sind, sind zwei Buszyklen erforderlich, um die Daten zu erhalten.
Einige Architekturen / Befehlssätze unterstützen keinen nicht ausgerichteten Zugriff und generieren bei solchen Versuchen eine Ausnahme. Daher erfordert der vom Compiler generierte nicht ausgerichtete Zugriffscode nicht nur zusätzliche Buszyklen, sondern auch zusätzliche Befehle, was ihn noch weniger effizient macht.
quelle
Auf PowerPC können Sie problemlos eine Ganzzahl von einer ungeraden Adresse laden.
Sparc und I86 und (glaube ich) Itatnium lösen Hardware-Ausnahmen aus, wenn Sie dies versuchen.
Eine 32-Bit-Last gegenüber vier 8-Bit-Lasten wird auf den meisten modernen Prozessoren keinen großen Unterschied machen. Ob sich die Daten bereits im Cache befinden oder nicht, hat eine weitaus größere Auswirkung.
quelle