struct mit Anforderungen (PC, x64, Windows und Linux, C++20)

Gast #6492224
Lesenswert?

1
// ...
2
constexpr std::align_val_t ALIGNMENT {32};
3
constexpr std::size_t SIZE {512}; // Garantiert ein Vielfaches von 32
4
// ...
5

6
struct alignas(ALIGNMENT) Foo
7
{    
8
  float a[SIZE]; // aligned
9
  float b[SIZE]; // garantiert aligned und keine Lücke davor?
10
  float c[SIZE]; // garantiert aligned und keine Lücke davor?
11
  int e = 0; // egal
12
  int f = 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?
#6492724
Lesenswert?

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.
Gast #6492858
Lesenswert?

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.
Beitrag #6492866 wurde von einem Moderator gelöscht.
Gast #6493397
Lesenswert?

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.
Gast #6493834
Lesenswert?

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!
Gast #6493856
Lesenswert?

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.
#6493896
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren