Approccio moderno alla creazione di std :: vector alloca memoria allineata


11

La seguente domanda è collegata, tuttavia le risposte sono vecchie e il commento dell'utente Marc Glisse suggerisce che ci sono nuovi approcci dal C ++ 17 a questo problema che potrebbero non essere adeguatamente discussi.

Sto cercando di far funzionare correttamente la memoria allineata per SIMD, pur avendo accesso a tutti i dati.

Su Intel, se creo un vettore float di tipo __m256e riduco le mie dimensioni di un fattore 8, mi dà memoria allineata.

Per esempio std::vector<__m256> mvec_a((N*M)/8);

In un modo un po 'confuso, posso lanciare puntatori su elementi vettoriali da float, il che mi consente di accedere a singoli valori float.

Preferirei invece avere un std::vector<float>allineato correttamente, e quindi può essere caricato in __m256e altri tipi SIMD senza segfaulting.

Ho esaminato align_alloc .

Questo può darmi un array in stile C che è correttamente allineato:

auto align_sz = static_cast<std::size_t> (32);
float* marr_a = (float*)aligned_alloc(align_sz, N*M*sizeof(float));

Tuttavia, non sono sicuro di come farlo std::vector<float>. Dare la std::vector<float>proprietà di marr_a non sembra essere possibile .

Ho visto alcuni suggerimenti che dovrei scrivere un allocatore personalizzato , ma questo sembra un sacco di lavoro, e forse con il C ++ moderno c'è un modo migliore?


1
senza segfaulting ... o senza potenziali rallentamenti delle suddivisioni della cache-line quando si utilizza _mm256_loadu_ps(&vec[i]). (Anche se nota che, con opzioni di ottimizzazione di default, GCC divide non-garantito-allineata a 256 bit carichi / negozi in vmovups XMM / vinsertf128. Quindi non v'è un vantaggio di utilizzare _mm256_loadpiù di loaduse si importa di come le compilazioni di codice su GCC se dimentica qualcuno a uso -mtune=...o -march=opzioni.)
Peter Cordes,

Risposte:


1

Tutti i contenitori nella libreria C ++ standard, inclusi i vettori, hanno un parametro modello opzionale che specifica l'allocatore del contenitore e non è davvero molto lavoro implementare il proprio:

class my_awesome_allocator {
};

std::vector<float, my_awesome_allocator> awesomely_allocated_vector;

Dovrai scrivere un po 'di codice che implementa il tuo allocatore, ma non sarebbe molto più codice di quello che hai già scritto. Se non hai bisogno del supporto pre-C ++ 17 devi solo implementare i metodi allocate () e deallocate () , tutto qui.


Devono anche specializzarsiallocator_traits
NathanOliver l'

1
Questo potrebbe essere un buon posto per una risposta canonica con un esempio che le persone possono copiare / incollare per saltare attraverso i fastidiosi cerchi di C ++. (Punti bonus se c'è un modo per lasciare che std :: vector tenti di riallocare sul posto invece del solito Braindead C ++ alloca sempre + copia.) Inoltre, ovviamente, questo vector<float, MAA>non è compatibile con il tipo vector<float>(e non può essere perché tutto ciò che fa .push_backsu un semplice std::vector<float>compilato senza questo allocatore potrebbe fare una nuova allocazione e copiarlo in una memoria minimamente allineata. E new / delete non è compatibile con align_alloc / free)
Peter Cordes

1
Non credo che ci sia alcuna garanzia che il puntatore restituito dall'allocatore venga utilizzato direttamente come indirizzo di base std::vectordell'array. Ad esempio, potrei immaginare un'implementazione std::vectordell'utilizzo di un solo puntatore alla memoria allocata che memorizza la fine / capacità / allocatore nella memoria prima dell'intervallo di valori. Ciò potrebbe facilmente ostacolare l'allineamento fatto dall'allocatore.
Dietmar Kühl,

1
Tranne che lo std::vectorgarantisce. Questo è quello per cui lo usa. Forse dovresti rivedere ciò che lo standard C ++ specifica qui.
Sam Varshavchik,

1
> Devono anche specializzarsi allocator_traits- No, non lo fanno. Tutto ciò che serve è implementare un allocatore conforme.
Andrey Semashev,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.