Pertanyaan berikut terkait, namun jawabannya sudah lama, dan komentar dari pengguna Marc Glisse menyarankan ada pendekatan baru sejak C ++ 17 untuk masalah ini yang mungkin tidak cukup dibahas.
Saya mencoba menyelaraskan memori yang berfungsi dengan baik untuk SIMD, sementara masih memiliki akses ke semua data.
Pada Intel, jika saya membuat vektor tipe float __m256
, dan mengurangi ukuran saya dengan faktor 8, itu memberi saya memori yang selaras.
Misalnya std::vector<__m256> mvec_a((N*M)/8);
Dengan cara yang sedikit kabur, saya bisa mengarahkan pointer ke elemen vektor untuk mengapung, yang memungkinkan saya untuk mengakses nilai float individual.
Sebagai gantinya, saya lebih suka memiliki std::vector<float>
yang disejajarkan dengan benar, dan dengan demikian dapat dimuat ke dalam __m256
dan jenis SIMD lainnya tanpa segfaulting.
Saya telah mencari di aligned_alloc .
Ini bisa memberi saya array gaya-C yang disejajarkan dengan benar:
auto align_sz = static_cast<std::size_t> (32);
float* marr_a = (float*)aligned_alloc(align_sz, N*M*sizeof(float));
Namun saya tidak yakin bagaimana melakukan ini std::vector<float>
. Memberi std::vector<float>
kepemilikan marr_a
tampaknya tidak mungkin .
Saya telah melihat beberapa saran bahwa saya harus menulis pengalokasi kustom , tetapi ini sepertinya banyak pekerjaan, dan mungkin dengan C ++ modern ada cara yang lebih baik?
_mm256_loadu_ps(&vec[i])
. (Meskipun catatan bahwa dengan pilihan tuning default, GCC membagi tidak dijamin-blok 256-bit beban / toko ke vmovups XMM / vinsertf128. Jadi ada adalah keuntungan untuk menggunakan_mm256_load
lebihloadu
jika Anda peduli tentang bagaimana mengkompilasi kode Anda di GCC jika lupa seseorang untuk gunakan-mtune=...
atau-march=
opsi.)Jawaban:
Semua kontainer di pustaka C ++ standar, termasuk vektor, memiliki parameter templat opsional yang menentukan pengalokasi penampung , dan itu tidak benar-benar banyak pekerjaan untuk menerapkan Anda sendiri:
Anda harus menulis sedikit kode yang mengimplementasikan pengalokasi Anda, tetapi itu tidak akan menjadi lebih banyak kode daripada yang sudah Anda tulis. Jika Anda tidak memerlukan dukungan pra-C ++ 17, Anda hanya perlu menerapkan metode alokasi () dan membatalkan alokasi () , itu saja.
sumber
allocator_traits
vector<float, MAA>
bukan tipe yang kompatibel denganvector<float>
(dan tidak bisa karena apa pun yang dilakukan.push_back
pada dataran yangstd::vector<float>
dikompilasi tanpa pengalokasi ini dapat melakukan alokasi baru dan menyalin ke memori minimal-aligned. Dan baru / delete tidak kompatibel dengan aligned_alloc / gratis)std::vector
array. Sebagai contoh, saya bisa membayangkan implementasistd::vector
menggunakan hanya satu pointer ke memori yang dialokasikan yang menyimpan akhir / kapasitas / pengalokasi dalam memori sebelum rentang nilai. Itu bisa dengan mudah menggagalkan penyelarasan yang dilakukan oleh pengalokasi.std::vector
menjaminnya. Untuk itulah ia menggunakannya. Mungkin Anda harus meninjau apa yang ditentukan oleh standar C ++ di sini.allocator_traits
- Tidak, mereka tidak. Yang diperlukan hanyalah menerapkan pengalokasi yang sesuai.