[GCC] Memory Alignment
-
Hiho! Ich hab eine Datenstruktur, die der GCC auf 16-Byte alignen soll:
class Vector3D { public: Vector3D(float x, float y, float y); Vector3D(const Vector3D& other); Vector3D(); // ... private: typedef float v4sf __attribute__ (( vector_size(4 * sizeof(float)) )); union { v4sf vec; float v[4]; } __attribute__((aligned(16))); };Das "attribue-aligned" sollte ja fuer das richtige Alignment des namenlosen union sorgen.
Wie schaut das jetzt aber innerhalb von anderen Datenstrukturen aus:class Triangle { public: // ... private: Vector3D v[3]; // ... };Ist nun garantiert, dass alle Array-Elemente innerhalb von Triangle richtig aligned sind? Und vor allen Dingen: wie schauts denn aus, wenn ein Triangle via "new" erstellt wird? Liefert new bereits richtig aligntes Stueck Speicher zurueck?
Mein Problem ist naemlich folgendes, dass folgendes assert manchmal schiefgeht:
inline Vector3D::Vector3D(float x, float y, float z) { assert((reinterpret_cast<int>(v) & 15) == 0); // proper alignment v[0] = x; v[1] = y; v[2] = z; v[3] = 0.f; }Und ich koennt mir evtl. vorstellen, dass das daran liegt, dass new ja ueberhaupt nicht weiss, dass es den allozierten Speicher richtig alignen soll. Lieg ich da richtig oder falsch und vor allen Dingen: wie beheb ich das Problem?
-
Blue-Tiger schrieb:
Das "attribue-aligned" sollte ja fuer das richtige Alignment des namenlosen union sorgen.
Wie schaut das jetzt aber innerhalb von anderen Datenstrukturen aus:Ist nun garantiert, dass alle Array-Elemente innerhalb von Triangle richtig aligned sind?
Ja. Das Alignment eines zusammengesetzten Typen ist immer mindestens so groß wie das strikteste Alignment seiner Elemente.
Und vor allen Dingen: wie schauts denn aus, wenn ein Triangle via "new" erstellt wird? Liefert new bereits richtig aligntes Stueck Speicher zurueck?
Ja und nein. Der globale Operator liefert immer Speicher, der hinreichend für ausgerichtet für jeden Standardtypen ist - ganz so wie malloc es tut. Allerdings benötigt in der Regel kein Standardtyp einen auf 16 Byte ausgerichteten Speicher. Du müsstest daher deinen eigenen Operator new überladen; entweder global oder klassenbezogen. Beides ist nicht ganz unproblematisch: eine globale Überladung wirkt sich mit praktisch jedem Typen aus und führt daher ggf. zu einiger Speicherverschwendung. Ein nur für die Klasse Vektor3D überladener Operator hilft dir nicht, wenn dein Vektor ein Member einer anderen Klasse sein soll.