Die folgende Frage ist verwandt, die Antworten sind jedoch alt, und der Kommentar von Benutzer Marc Glisse legt nahe, dass es seit C ++ 17 neue Ansätze für dieses Problem gibt, die möglicherweise nicht angemessen diskutiert werden.
Ich versuche, den ausgerichteten Speicher für SIMD ordnungsgemäß zu verwenden, während ich weiterhin auf alle Daten zugreifen kann.
Wenn ich unter Intel einen Float-Vektor vom Typ erstelle __m256
und meine Größe um den Faktor 8 reduziere, habe ich einen ausgerichteten Speicher.
Z.B std::vector<__m256> mvec_a((N*M)/8);
Auf eine etwas hackige Weise kann ich Zeiger auf Vektorelemente umwandeln, um zu schweben, wodurch ich auf einzelne Gleitkommawerte zugreifen kann.
Stattdessen würde ich es vorziehen, eine zu haben, std::vector<float>
die korrekt ausgerichtet ist und somit __m256
ohne Segfaulting in und andere SIMD-Typen geladen werden kann.
Ich habe mich mit align_alloc befasst .
Dies kann mir ein Array im C-Stil geben, das korrekt ausgerichtet ist:
auto align_sz = static_cast<std::size_t> (32);
float* marr_a = (float*)aligned_alloc(align_sz, N*M*sizeof(float));
Ich bin mir jedoch nicht sicher, wie ich das machen soll std::vector<float>
. Das std::vector<float>
Eigentum an zu geben marr_a
scheint nicht möglich zu sein .
Ich habe einige Vorschläge gesehen, dass ich einen benutzerdefinierten Allokator schreiben sollte , aber das scheint viel Arbeit zu sein, und vielleicht gibt es mit modernem C ++ einen besseren Weg?
_mm256_loadu_ps(&vec[i])
. (Beachten Sie jedoch, dass GCC mit den Standardoptimierungsoptionen nicht garantiert ausgerichtete 256-Bit-Ladevorgänge / -Speicher in vmovups xmm / vinsertf128 aufteilt. Daher ist die Verwendung von_mm256_load
over von Vorteil,loadu
wenn Sie sich darum kümmern, wie Ihr Code auf GCC kompiliert wird, wenn jemand dies vergisst Verwendung-mtune=...
oder-march=
Optionen.)Antworten:
Alle Container in der Standard-C ++ - Bibliothek, einschließlich Vektoren, verfügen über einen optionalen Vorlagenparameter , der den Allokator des Containers angibt , und es ist nicht wirklich viel Arbeit, einen eigenen zu implementieren:
Sie müssen ein wenig Code schreiben, der Ihren Allokator implementiert, aber es wäre nicht viel mehr Code als Sie bereits geschrieben haben. Wenn Sie keine Unterstützung vor C ++ 17 benötigen, müssen Sie nur die Methoden allocate () und deallocate () implementieren .
quelle
allocator_traits
vector<float, MAA>
nicht typkompatibel istvector<float>
(und nicht daran liegen kann) Alles, was.push_back
auf einer Ebene ausgeführt wird,std::vector<float>
die ohne diesen Zuweiser kompiliert wurde, könnte eine neue Zuordnung vornehmen und in einen minimal ausgerichteten Speicher kopieren. Und new / delete ist nicht kompatibel mit align_alloc / free)std::vector
Arrays des Arrays verwendet wird. Zum Beispiel könnte ich mir eine Implementierung vorstellen, bei derstd::vector
nur ein Zeiger auf den zugewiesenen Speicher verwendet wird, der das Ende / die Kapazität / den Allokator vor dem Wertebereich im Speicher speichert. Dies könnte die Ausrichtung des Allokators leicht vereiteln.std::vector
garantiert es. Dafür wird es verwendet. Vielleicht sollten Sie überprüfen, was der C ++ - Standard hier spezifiziert.allocator_traits
- Nein, das tun sie nicht. Sie müssen lediglich einen kompatiblen Allokator implementieren.