Frage

Was ist der Unterschied zwischen ausgerichtetem und nicht ausgerichteten Speicherzugriff?

Ich arbeite an einem TMS320C64x DSP, und ich mag die intrinsischen Funktionen (C-Funktionen für Montageanleitung) verwenden, und es hat

ushort & _amem2(void *ptr);
ushort & _mem2(void *ptr);

wobei _amem2 Motor hat einen ausgerichteten Zugriff von 2 Bytes und _mem2 tut unausgerichteten Zugriff.

Wann sollte ich welche?

War es hilfreich?

Lösung

Ein ausgerichteter Speicherzugriff bedeutet, dass der Zeiger (als eine ganze Zahl) ein Vielfach eines typspezifischen Wertes ist die Ausrichtung genannt. Die Ausrichtung ist die natürliche Adresse mehr wo der Typ sein, oder sollte (z.B. aus Leistungsgründen) gespeichert wird auf einer CPU. Zum Beispiel könnte eine CPU erfordern, dass alle Zwei-Byte-Ladungen oder Speicherungen werden durch Adressen durchgeführt, die ein Vielfaches von zwei sind. Für kleine primitive Typen (unter 4 Bytes) ist die Ausrichtung fast immer die Größe des Typs. Für structs ist die Ausrichtung in der Regel die maximale Ausrichtung eines Mitglieds.

Der C-Compiler setzt immer Variablen, die Sie unter den Adressen angeben, die die „richtige“ Ausrichtung erfüllen. Also, wenn ptr Punkte z.B. eine uint16_t Variable, wird es ausgerichtet und können Sie verwenden _amem2. Sie brauchen nur verwenden _mem2 wenn Sie zugreifen, z eine gepackte Byte-Array empfangen über I / O oder Bytes in der Mitte einer Zeichenfolge.

Andere Tipps

Viele Computerarchitekturen speichern Speicher in „Worte“ von mehreren Bytes je. Zum Beispiel speichert der Intel 32-Bit-Architektur Worten von 32 Bits, die jeweils aus 4 Bytes. Der Speicher ist auf der Single-Byte-Ebene angegangen, jedoch; Daher kann eine Adresse „ausgerichtet“ werden, was bedeutet, es beginnt an einer Wortgrenze, oder „nicht ausgerichtet“, was bedeutet, es funktioniert nicht.

Auf bestimmte Architekturen bestimmte Speicheroperationen langsamer sein können oder auch nicht vollständig auf nicht ausgerichteten Adressen erlaubt.

Also, wenn Sie wissen, Ihre Adressen auf die richtigen Adressen ausgerichtet sind, können Sie _amem2 (), für die Geschwindigkeit nutzen. Andernfalls sollten Sie verwenden _mem2 ().

Aligned Adressen sind diejenigen, die ein Vielfaches der Zugriffsgröße in Frage sind.

  • Zugriff von 4-Byte-Wörter auf Adressen, die Vielfaches von 4 sind, werden ausgerichtet werden
  • Zugriff von 4 Bytes von der Adresse (sagen wir) 3 wird nicht ausgerichteten Zugriff

Es ist sehr wahrscheinlich, dass die _mem2 Funktion, die für nicht ausgerichtete Zugriffe auch funktionieren wird weniger optimal die richtigen Ausrichtungen in seinem Code zum Laufen zu bringen. Dies bedeutet, dass die _mem2 Funktion ist wahrscheinlich sein kostspieligen dann seine _amem2 Version.

Also, wenn Sie die Leistung benötigen (insbesondere, wenn Sie wissen, dass die Zugriffslatenz hoch ist), wäre es klug zu identifizieren, wenn Sie den ausgerichteten Zugang nutzen können. Die _amem2 gibt es für diesen Zweck -. Sie Leistung zu geben, wenn Sie den Zugriff wissen ausgerichtet ist,

Wenn es um 2 Byte kommt greift, ausgerichtet Operationen zu identifizieren ist sehr einfach.
Wenn die alle Zugriffsadressen für den Betrieb sind ‚gerade‘ (das heißt, ihr LSB ist Null), Sie haben 2-Byte-Ausrichtung. Dies kann mit leicht überprüft werden,

if (address & 1) // is true
    /* we have an odd address; not aligned */
else
    /* we have an even address; its aligned to 2-bytes */

Ich weiß, das ist eine alte Frage mit einer Antwort ausgewählt, aber didnt sehe jemand die Antwort erklären, was ist der Unterschied zwischen ausgerichtetem und nicht ausgerichteten Speicherzugriff ...

Ob DRAM- oder SRAM oder Flash-Speicher oder andere. Nehmen Sie eine sram als ein einfaches Beispiel es aus Bits eine bestimmte sram gebaut wird, breit aus einer festen Anzahl von Bits gebaut werden und eine feste Anzahl von Zeilen tief. 32 Bit breit sagen läßt und mehr / viele Reihen tief.

wenn ich einen 32-Bit-Schreib tue 0x0000 in diesem sram zu adressieren, die Speicher-Controller, um dieses sram kann einfach einen einzigen Schreibzyklus tun 0 zu bringen.

wenn ich einen 32-Bit-Schreib tue 0x0001 in diesem sram zu adressieren, dass unter der Annahme, erlaubt ist, die Steuerung muss eine Lese von Zeile 0, tun, drei des Bytes ändern, die Erhaltung eines, und schreibt, dass 0 rudern, dann liest Zeile 1 ein Byte verläßt die anderen drei als gefunden ändern und das zurück schreiben. das Bytes geändert erhalten oder nicht mit endianness für das System zu tun hat.

Die ehemalige ausgerichtet ist und diese nicht ausgerichtet, eindeutig ein Unterschied in der Leistung und benötigt die zusätzliche Logik, um die vier Speicherzyklen in der Lage sein zu tun, und die Byte-Spuren zusammenführen.

Wenn ich 32 Bit von Adresse 0x0000 lesen dann einer einzigen Lese von Zeile 0, getan. Aber lesen von 0x0001 und ich habe zu tun, zwei liest ROW0 und row1 und je nach Systemauslegung nur diese 64 Bits zurück an den Prozessor möglicherweise zwei Bus-Takten statt einer schicken. oder die Speichersteuereinheit hat die zusätzliche Logik, so daß die 32 Bits auf dem Datenbus in einem Buszyklus ausgerichtet sind.

16 Bit liest sind ein wenig besser, ein Lesen von 0x0000, 0x0001 und 0x0002 nur ein Lesen von ROW0 sein würde und auf dem System / Prozessor-Design basiert könnten diese 32 Bits zurück, und der Prozessor extrahiert sie oder verschieben sie in der schicken Speicher-Controller, so dass sie auf bestimmte Bytebahnen landen so der Prozessor muß nicht um drehen haben. Der eine oder andere hat, wenn nicht beide. Ein Lesevorgang von 0x0003 ist aber, wie oben Sie Zeile 0 und Zeile 1 als eine Ihrer Bytes in jedem zu lesen ist, und dann entweder 64 Bits zurück für den Prozessor kombiniert zu extrahieren senden oder die Speichersteuerung, die Bits in eine 32-Bit-Bus-Antwort ( den Bus zwischen dem Prozessor und dem Speicher-Controller unter der Annahme ist 32 Bit breit für diese Beispiele).

Ein 16-Bit-Schreib obwohl endet immer mit mindestens einem RMW-Befehl in diesem Beispiel sram, Adresse 0x0000, 0x0001 und 0x0002 Lese bis ROW0 zwei Bytes ändern und zurückschreiben. Adresse 0x0003 lesen zwei Zeilen ändern jeweils ein Byte und zurückschreiben.

8-Bit benötigen Sie nur eine Zeile zu lesen, dass der Byte enthält, schreibt obwohl eine Read-Modify-Write einer Zeile ist.

Die ARMv4 nur knapp sein Ziel wie unaligned obwohl Sie die Falle deaktivieren könnte, und das Ergebnis ist nicht wie Sie oben, ist nicht wichtig, aktuelle Arme, um die oben beschriebene Verhalten erwarten würde erlauben unaligned und geben Sie Ihnen ein wenig in einem Steuerregister ändern kann und dann wird nicht ausgerichteten Transfer abbrechen. Mips verwendet, um nicht zulassen, nicht sicher, was sie jetzt tun. x86 usw. 68K wurde erlaubt und der Speichercontroller gehabt haben die meiste Arbeit zu tun.

Die Designs, die es eindeutig für die Leistung sind erlauben Dont und weniger Logik an, was manche würden sagen ist eine Belastung für die Programmierer andere vielleicht sagen, es ist keine zusätzliche Arbeit auf dem Programmiergerät oder einfacher auf den Programmierern. ausgerichtet ist oder nicht, können Sie auch sehen, warum es besser sein, nicht zu versuchen, jeden Speicher zu sparen, indem sie 8-Bit-Variablen, aber gehen Sie vor und brennen Sie ein 32-Bit-Wort oder was auch immer die natürliche Größe eines Registers oder der Bus. Es kann Ihre Leistung bei geringen Kosten einiger Bytes helfen. Ganz zu schweigen von dem zusätzlichen Code der Compiler hinzuzufügen brauchen würden, um das sagen kann 32-Bit-Register ahmen ein 8-Bit-Variable, Maskierung und manchmal Verlängerung unterschreiben. Wo Größen Register nativer diese zusätzlichen Anweisungen verwenden sind nicht erforderlich. Sie können auch mehrere Dinge in einen Bus / Speicher breiten Stelle und führen Sie einen Speicherzyklus zu sammeln oder schreiben sie dann verwenden, um einige zusätzliche Anweisungen zu m packenanipulate zwischen den Registern nicht Kalkulations RAM und eine mögliche Wäsche auf der Anzahl von Instruktionen.

Ich bin damit einverstanden nicht, dass die Compiler die Daten direkt für das Ziel immer auszurichten, gibt es Möglichkeiten, dass zu brechen. Und wenn das Ziel muß nicht unaligned unterstützen Sie die Fehler betroffen. Programmierer würden nie darüber reden müssen, wenn der Compiler immer hat es richtig auf jedem Recht Code basierte Sie einfiel, gibt es keinen Grund für diese Frage sei, wenn es nicht für die Leistung ist. wenn Sie die Leere ptr Adresse steuern nicht auf ausgerichtet werden oder nicht, dann müssen Sie die mem2 () verwenden, nicht ausgerichteten Zugriff die ganze Zeit oder Sie tun müssen, einen if-then-else in Ihrem Code basierend auf dem Wert des ptr als nik wies darauf hin. indem er erklärt, der C-Compiler hat jetzt keine Möglichkeit, diese als ungültig richtig mit Ihrer Ausrichtung umgehen und es wird nicht garantiert werden. wenn Sie ein char * prt nehmen und ihn auf diese Funktionen sind alle Wetten ab auf den Compiler es immer richtig, ohne dass Sie zusätzlichen Code Zugabe entweder in der mem2 () Funktion oder außerhalb dieser beiden Funktionen begraben. so wie in Ihrer Frage mem2 geschrieben () ist die einzig richtige Antwort.

DRAM sagen in Ihrem Desktop / Laptop verwendet neigt dazu, 64 oder 72 zu sein (mit ecc) Bits breit, und jeder Zugriff auf sie ausgerichtet ist. Auch wenn sich die Memory-Sticks sind tatsächlich aus 8 Bit breite oder 16 oder 32 Bit breiten Chips. die Speichersteuerung und im Idealfall mindestens eine Cache sitzt vor diesem dram (dies kann mit Telefonen / Tabletten aus verschiedenen Gründen zu ändern), so dass die nicht ausgerichteten oder sogar Zugänge ausgerichtet ist, die kleiner ist als die Busbreite ist Lese-Modifizier-Schreibvorgänge behandelt mit in dem Cache-SRAM, der viel schneller ist, und die DRAM-Zugriffe werden alle voll Busbreite zugreift ausgerichtet sind. Wenn Sie keine Cache vor dem Dram haben und die Steuerung ist für die volle Breite ausgelegt greifen dann, dass die schlechteste Leistung ist, entworfen, wenn für die Byte-Spuren separat leuchten (vorausgesetzt, 8 Bit breite Chips), dann müssen Sie nicht die haben Read-Modify -writes aber eine kompliziertere Steuerung. wenn der typische Anwendungsfall mit einem Cache ist (wenn es eine in der Konstruktion ist), dann kann es nicht sinnvoll, für jede Byte Spur, dass zusätzliche Arbeiten in der Steuerung zu haben, aber habe es nur wissen, wie voll Busbreite große Transfers zu tun oder ein Vielfaches von.

_mem2 ist allgemeiner. Es wird funktionieren, wenn ptr ausgerichtet ist oder nicht. _amem2 ist strenger: es erfordert, dass ptr ausgerichtet sein (wenn auch vermutlich etwas effizienter). So verwenden _mem2, wenn Sie garantieren können, dass ptr ist immer ausgerichtet ist.

Viele Prozessoren haben Ausrichtung Einschränkungen beim Speicherzugriff. Nicht ausgerichteter Zugriff entweder erzeugt ein Ausnahme-Interrupt (z.B. ARM), oder nur langsamer (zum Beispiel x86).

ist _mem2 wahrscheinlich als das Abrufen zwei Bytes umgesetzt und mit Shift und oder bitweise Operationen eine 16-Bit machen ushort aus ihnen heraus.

_amem2 wahrscheinlich nur liest den 16-Bit-ushort aus dem angegebenen ptr.

Ich weiß nicht, TMS320C64x speziell, aber ich würde vermuten, es erfordert 16-Bit-Ausrichtung für 16-Bit-Speicherzugriffe. So können Sie _mem2 immer verwenden, aber mit Leistungseinbußen und _amem2, wenn Sie, dass ptr garantieren kann, ist eine gerade Adresse.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top