Forum: PC-Programmierung struct mit Anforderungen (PC, x64, Windows und Linux, C++20)


von Franz-Xaver (Gast)


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?

von Rolf M. (rmagnus)


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.

von mh (Gast)


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.
von A. S. (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von udok (Gast)


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.

von Franz-Xaver (Gast)


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!

von mh (Gast)


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.

von Rolf M. (rmagnus)


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.

von udok (Gast)


Lesenswert?

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?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.