Speicherausrichtung
# Speicherausrichtung

In der Rechnerarchitektur (Computer) bezeichnet man ein Datenelement (oder einen Operanden) mit n Bytes als im Speicher ausgerichtet (englisch Data Alignment, Data Structure Padding), wenn dessen Adresse A ein ganzzahliges Vielfaches von n ist (A mod n = 0). Falls n keine Potenz von 2 ist, muss für die Berechnung n auf die nächsthöhere Potenz von 2 aufgerundet werden. Beispiel: Ein 5-Byte-Datenelement muss entsprechend einem 8-Byte-Datenelement ausgerichtet werden.

Ist die Adresse eines Mehrbyte-Datenelements kein derartiges Vielfaches, so ist es nicht ausgerichtet (englisch Data Misalignment). Ein 1-Byte-Datenelement ist jedoch immer ausgerichtet.

Typischerweise erfolgt eine byteweise Adressierung des Arbeitsspeichers, und pro Takt kann auf eine Folge von m Bytes zugegriffen werden. Die Anzahl m ist die Breite des Datenbusses in Bytes. Übliche Datenbusbreiten sind 16 Bit (m = 2), 32 Bit (m = 4) und 64 Bit (m = 8).

Sind die Operanden im Speicher ausgerichtet, so ist bei n kleiner gleich m nur jeweils ein Speicherzugriff nötig. Auch bei n größer m sind grundsätzlich nur die jeweils minimale Anzahl von Speicherzugriffen nötig. Der Nachteil der Speicherausrichtung besteht darin, dass ggf. der Speicher nicht lückenlos genutzt werden kann. Bei obigem Beispiel des 5-Byte-Datenelements bleiben drei Achtel des Speichers ungenutzt.

Sind die Operanden im Speicher nicht ausgerichtet, so ist eine lückenlose Nutzung des Speichers auch bei beliebiger Mischung der Datenformate möglich. Allerdings müssen abhängig von der zufälligen Anordnung ggf. mehr Speicherzugriffe erfolgen, als eigentlich für ein solches Datenelement minimal nötig wären. Durch zusätzliche Shiftoperationen müssen die Operandenteile danach erst wieder zusammengesetzt werden. (Genau genommen sind bei n größer m auch Shift-Operationen nötig, die aber bei vorgegebener Datenbusbreite unvermeidlich und somit kein "data misalignment" sind.)

Je nach benutzter Prozessorarchitektur wird ein Zugriff auf nicht ausgerichtete Daten hardwareseitig gar nicht unterstützt. In diesem Falle müsste eine spezielle Programmroutine, welche die Daten softwareseitig zusammensetzt, implementiert und für jeden Zugriff ausgeführt werden. Der Mehraufwand geht damit weit über bloße zusätzliche Speicherzugriffe hinaus.

Die Speicherausrichtung wird nur thematisiert, um die Zahl der Speicherzugriffe durch Automatismen bei der Anordnung von Datenelementen zu minimieren. Dass bei n = m + 1 unabhängig von der Speicherausrichtung immer zwei Speicherzugriffe nötig sind, zeigt die Grenzen der eingangs aufgestellten Regeln. Beim schon mehrfach benutzten Beispiel des 5-Byte-Datenelements könnte zunächst bei 4 Byte Datenbusbreite eine korrekte Speicherausrichtung als überflüssig eingestuft werden. Falls jedoch später eine Portierung auf einen doppelt so breiten Datenbus erfolgt, wird die unterlassene Speicherausrichtung zusätzlich Aufwände fordern.

Ein weiterer Sonderfall 2n = 3m könnte, wenn er nicht mit dem vorherigen Sonderfall zusammentrifft, eine halbherzige Speicherausrichtung zweckmäßig erscheinen lassen: Eine beispielhafte Folge von mehreren 6-Byte-Datenelementen kann bei 4 Byte Datenbusbreite entweder gut, besser oder schlecht ausgerichtet werden. Gut wäre es, für das erste Datenelement die Regeln zur Speicherausrichtung zu beachten und weitere Datenelemente bündig anzuschließen. Es wären immer jeweils zwei Zugriffe nötig. Besser wäre es, eine mögliche Portierung auf einen doppelt so breiten Datenbus kritisch zu hinterfragen und ggf. gleich eine regelkonforme Speicherausrichtung zu betreiben.

In der Praxis war und ist es üblich, die Daten eine Stufe höher als für die Zielmaschine notwendig auszurichten, um wenigstens eine Busbreiten-Verdopplung einzuplanen: Auf 8-Bit-Computern wurden und werden 16-Bit-Werte vorsorglich auf geraden Adressen abgelegt, und bei heutigen 64-Bit-Prozessoren werden 128-Bit-Ausrichtungen empfohlen bzw. von Compilern eingehalten.

