Std yapmak için modern yaklaşım :: vektör hizalanmış bellek ayırmak


11

Aşağıdaki soru cevaplar eski ancak, ilgili ve kullanıcı gelen açıklama edilir Marc Glisse yeterince ele olabilir bu soruna 17 C ++ yana yeni yaklaşımlar olduğunu öne sürüldü.

Hala tüm verilere erişirken, SIMD için düzgün çalışan hizalanmış bellek almaya çalışıyorum.

Intel'de, kayan bir tür vektörü oluşturur ve boyutumu __m2568 kat azaltırsam, bana hizalanmış bellek verir.

Örneğin std::vector<__m256> mvec_a((N*M)/8);

Biraz hacky bir şekilde, vektör öğeleri için yüzer işaretçiler belirtebilir, bu da bireysel şamandıra değerlerine erişmeme izin verir.

Bunun yerine, std::vector<float>doğru hizalanmış ve böylece __m256segfaulting olmadan diğer SIMD tiplerine yüklenebilir ve tercih ederim .

Align_alloc içine bakıyordum .

Bu bana doğru hizalanmış bir C stili dizi verebilir:

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

Ancak bunun için nasıl yapılacağından emin değilim std::vector<float>. std::vector<float>Sahipliğini vermek marr_a mümkün görünmüyor .

Özel bir ayırıcı yazmam gerektiğine dair bazı öneriler gördüm , ancak bu çok fazla iş gibi görünüyor ve belki de modern C ++ ile daha iyi bir yol var mı?


1
segfaulting olmadan ... veya kullandığınızda önbellek hattındaki olası yavaşlamalar olmadan _mm256_loadu_ps(&vec[i]). Varsayılan ayar seçenekleri ile, GCC notu o rağmen ( böler 256 bit yükler / mağaza-garanti hizalanmış vmovups xmm / vinsertf128 içine. Yani olup kullanmanın bir avantaj _mm256_loadüzerinde loaduönemsediğiniz eğer nasıl GCC üzerinde kod derlenir birisi unutuyor eğer kullanmak -mtune=...veya -march=seçenekleri).
Peter Cordes

Yanıtlar:


1

Vektörler dahil olmak üzere standart C ++ kitaplığındaki tüm kaplarda , kabın ayırıcısını belirten isteğe bağlı bir şablon parametresi vardır ve kendinizinkini uygulamak için çok fazla iş yoktur:

class my_awesome_allocator {
};

std::vector<float, my_awesome_allocator> awesomely_allocated_vector;

Allocator'ınızı uygulayan biraz kod yazmanız gerekecek, ancak daha önce yazdığınızdan çok daha fazla kod olmaz. C ++ 17 öncesi desteğe ihtiyacınız yoksa, sadece tahsis () ve deallocate () yöntemlerini uygulamanız yeterlidir , hepsi bu.


Ayrıca uzmanlaşmaları gerekiyorallocator_traits
NathanOliver

1
Bu, insanların C ++ 'ın can sıkıcı çemberlerinden atlamak için kopyalayabileceği / yapıştırabileceği bir örnekle kanonik bir cevap için iyi bir yer olabilir. (Std :: vector'un her zamanki braindead C ++ yerine yerinde yeniden tahsis etmesine izin vermenin bir yolu varsa, bonus puanlar her zaman + kopya ayırır.) Ayrıca, bunun türle vector<float, MAA>uyumlu olmadığını da unutmayın vector<float>(çünkü does şey .push_backbir ovada std::vector<float>bu ayırıcı olmadan derlenmiş yeni tahsisini yapmak ve kopya minimal hizalanmış belleğe ve yeni / silme) / aligned_alloc uyumlu özgür değildir olabilir.
Peter Cordes

1
Allocator döndürülen işaretçi doğrudan std::vector's dizisinin temel adresi olarak kullanılan herhangi bir garanti olduğunu sanmıyorum . Örneğin std::vector, ayrılan belleğe, değerler / aralık / ayırıcıyı değerler aralığından önce bellekte saklayan bir işaretçi kullanıldığını hayal edebiliyorum . Bu, ayırıcı tarafından yapılan hizalamayı kolayca folyolayabilir.
Dietmar Kühl

1
Dışında bunu std::vectorgaranti eder. Bunun için kullanır. Belki de C ++ standardının burada belirttiklerini gözden geçirmelisiniz.
Sam Varshavchik

1
> Ayrıca uzmanlaşmaları gerekiyor allocator_traits- Hayır, bilmiyorlar. Tek gereken, uyumlu bir ayırıcı uygulamaktır.
Andrey Semashev
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.