constexprstd::size_tSIZE{512};// Garantiert ein Vielfaches von 32
4
// ...
5
6
structalignas(ALIGNMENT)Foo
7
{
8
floata[SIZE];// aligned
9
floatb[SIZE];// garantiert aligned und keine Lücke davor?
10
floatc[SIZE];// garantiert aligned und keine Lücke davor?
11
inte=0;// egal
12
intf=0;// egal
13
};
// ...
auto foos = new Foo[1000]; // Seit C++17 wird dabei das 'alignas'
berücksichtigt, soweit ich weiß.
// ...
Folgende zwei Dinge müssen garantiert sein (weswegen "ausprobieren und
nachschauen" nicht ausreicht):
1. Jedes der Arrays muss 32-Byte-aligned sein (wegen SIMD/AVX).
2. Die 3 Arrays sollen jeweils im Speicher direkt aufeinander folgen und
für jedes Foo mit einem einzigen std::fill / memset bei Bedarf auf 0
gesetzt werden bzw. in einem Rutsch per std::copy / memcpy in eine
andere Foo-Struktur kopiert können (statt mit jeweils drei Aufrufen).
Ich bin mir nicht ganz sicher, ob die obige struct-Definition ausreicht,
um immer beide Anforderungen zu erfüllen. Falls dies nicht der Fall ist:
Wie müsste sie aussehen?
Franz-Xaver schrieb:> Ich bin mir nicht ganz sicher, ob die obige struct-Definition ausreicht,> um immer beide Anforderungen zu erfüllen. Falls dies nicht der Fall ist:> Wie müsste sie aussehen?
Ich bin mir auch nicht sicher, würde aber vermuten, dass die Garantie
für die Arrays b und c nicht gegeben ist.
Franz-Xaver schrieb:> Falls dies nicht der Fall ist:> Wie müsste sie aussehen?
Hmm, falls die drei Arrays immer gleich groß sind, könntest du sie
vielleicht selbst wieder in ein Array stecken. Dann gibt es keine Lücke
und dadurch auch implizit das richtige Alignment.
Franz-Xaver schrieb:> Folgende zwei Dinge müssen garantiert sein (weswegen "ausprobieren und> nachschauen" nicht ausreicht):>> 1. Jedes der Arrays muss 32-Byte-aligned sein (wegen SIMD/AVX).
Ich sehe keinen Grund, warum es garantiert sein sollte.
> 2. Die 3 Arrays sollen jeweils im Speicher direkt aufeinander folgen und> für jedes Foo mit einem einzigen std::fill / memset bei Bedarf auf 0> gesetzt werden bzw. in einem Rutsch per std::copy / memcpy in eine> andere Foo-Struktur kopiert können (statt mit jeweils drei Aufrufen).
Zumindest copy/memcpy sollten auch möglich sein, wenn es padding
zwischen den arrays gibt, musst nur etwas mehr kopieren.
> Ich bin mir nicht ganz sicher, ob die obige struct-Definition ausreicht,> um immer beide Anforderungen zu erfüllen. Falls dies nicht der Fall ist:> Wie müsste sie aussehen?
Muss es garantiert sein, oder reicht es, wenn der Compiler mit einer
Fehlermeldung abbricht, wenn die Bedingungen nicht erfüllt sind? Das
sollte mit static_assert und ein paar sizeof und alignof möglich sein.
Franz-Xaver schrieb:> Folgende zwei Dinge müssen garantiert sein (weswegen "ausprobieren und> nachschauen" nicht ausreicht):
Dann mache ein CompileTime-Assert darauf. Also dass die Adressen genau
dort sind (relativ), wo Du sie erwartest.
Ich würde auch sagen, dass ein static_assert reicht, denn auch wenn das
gewünschte Alignment nicht garantiert ist, so ist es doch äußerst
wahrscheinlich. Und falls es mal je doch nicht so sein sollte, sagt dir
das der Compiler über den static_assert.
Die Arrays sind klarerweise 32 Bytes aligned,
wenn das struct 32 Bytes aligned ist.
Der Compiler wäre ja schön blöd, wenn er Lücken rein machen würde.
Mit dem Microsoft Compiler kannst du __declspec(align(32)) vor jedem
Array verwenden, damit is es dann 100% festgenagelt.
Danke für die Antworten. Das mit dem static_assert ist eine gute Idee,
werde ich machen.
udok schrieb:> Der Compiler wäre ja schön blöd, wenn er Lücken rein machen würde.
Schon richtig, aber "darf" er vielleicht doch irgendwann aus dem Gebüsch
springen, um mir den Tag zu versauen? Das war mein Gedanke.
> Mit dem Microsoft Compiler kannst du __declspec(align(32)) vor jedem> Array verwenden, damit is es dann 100% festgenagelt.
Stimmt; es sollte auch mit "alignas" (kompatibel) funktionieren.
--------
Danke nochmal an alle und einen schönen (Rest-) 1. Advent!
Franz-Xaver schrieb:>> Mit dem Microsoft Compiler kannst du __declspec(align(32)) vor jedem>> Array verwenden, damit is es dann 100% festgenagelt.>> Stimmt; es sollte auch mit "alignas" (kompatibel) funktionieren.
Ka wie das bei Microsoft ist, aber alignas (gibts seit c++11) ist eine
untere Grenze. Wenn du alignas(32) dran schreibst, kann der Compiler
auch ein alignas(64) draus machen, wenn er es für richtig hält.
udok schrieb:> Die Arrays sind klarerweise 32 Bytes aligned,> wenn das struct 32 Bytes aligned ist.> Der Compiler wäre ja schön blöd, wenn er Lücken rein machen würde.
Das war aber nict die Frage. Die Frage war, ob C++ das garantiert, und
das tut es nicht.
> Mit dem Microsoft Compiler kannst du __declspec(align(32)) vor jedem> Array verwenden, damit is es dann 100% festgenagelt.Franz-Xaver schrieb:>> Mit dem Microsoft Compiler kannst du __declspec(align(32)) vor jedem>> Array verwenden, damit is es dann 100% festgenagelt.>> Stimmt; es sollte auch mit "alignas" (kompatibel) funktionieren.
Wobei dir das auch nur das passende Alignment der Arrays garantiert und
nicht, dass sie lückenlos hintereinander stehen.
Wenn man bei einem so einfachen struct Layout soviel zittert,
dann kann man noch alle drei Arrays als ein Array deklarieren.
Aber wer garantiert mir, dass morgen die Sonne aufgeht?