Bellek bant genişliği sınırlı hesaplamalar paylaşılan bellek ortamlarında (ör. OpenMP, Pthreads veya TBB aracılığıyla iş parçacığı) gerçekleştirildiğinde, belleğin fiziksel bellekte doğru bir şekilde dağıtılmasının nasıl sağlanacağına dair bir ikilem vardır; "yerel" bellek veri yolu. Arabirimler taşınabilir olmasa da, çoğu işletim sisteminin iş parçacığı benzeşimini ayarlama yolları vardır (örneğin pthread_setaffinity_np()
birçok POSIX sisteminde, sched_setaffinity()
Linux'ta, SetThreadAffinityMask()
Windows'ta). Bellek hiyerarşisini belirlemek için hwloc gibi kütüphaneler de vardır , ancak maalesef çoğu işletim sistemi henüz NUMA bellek politikalarını ayarlamak için yollar sağlamamaktadır. Linux, libnuma ile dikkate değer bir istisnadıruygulamanın bellek politikasını ve sayfa geçişini sayfa ayrıntı düzeyinde değiştirmesine olanak tanır (2004'ten bu yana ana hattadır, dolayısıyla yaygın olarak bulunur). Diğer işletim sistemleri, kullanıcıların örtük bir "ilk dokunma" politikası izlemesini bekler.
"İlk dokunma" ilkesi ile çalışmak, arayanın yeni ayrılan belleğe ilk yazarken daha sonra kullanmayı planladığı yakınlıkla ileti oluşturması ve dağıtması gerektiği anlamına gelir. (Çok az sistemleri şekilde yapılandırılmış malloc()
sadece gerçekte hatalı olduğunda farklı iş parçacıkları tarafından belki de onları bulmak için vaat, aslında sayfaları bulur.) Bu kullanarak bu tahsisi ima calloc()
veya hemen kullanarak tahsisi sonrasında hafızasını başlatılıyor memset()
o arıza eğiliminde olacaktır çünkü zararlıdır tüm belleği, ayırma iş parçacığını çalıştıran çekirdeğin bellek veri yoluna bağlayarak, belleğe birden çok iş parçacığından erişildiğinde en kötü bellek bant genişliğine yol açar. Aynı şey new
birçok yeni tahsinin başlatılmasında ısrar eden C ++ operatörü için de geçerlidir (ör.std::complex
). Bu çevre ile ilgili bazı gözlemler:
- Ayırma "iş parçacığı toplu" olarak yapılabilir, ancak şimdi ayırma, farklı iş parçacığı modelleri (belki de her biri kendi iş parçacığı havuzları olan) kullanarak istemcilerle etkileşim kurmak zorunda kalabilen kitaplıklar için istenmeyen iş parçacığı modeline karıştırılır.
- RAII, idiyomatik C ++ 'ın önemli bir parçası olarak kabul edilir, ancak bir NUMA ortamında bellek performansı için aktif olarak zararlı gibi görünüyor. Yerleşim
new
, ayrılan bellekmalloc()
veya rutinlerle kullanılabilirlibnuma
, ancak bu ayırma işlemini değiştirir (ki bu gerekli olduğuna inanıyorum). - DÜZENLEME: İşleç hakkındaki önceki ifadem
new
yanlıştı, birden çok argümanı destekleyebilir, Chetan'ın cevabına bakın. Hala belirtilen afiniteyi kullanmak için kütüphanelerin veya STL kaplarının elde edilmesiyle ilgili bir endişe olduğuna inanıyorum. Birden çok alan paketlenmiş olabilir ve örneğinstd::vector
doğru bağlam yöneticisi etkin olarak yeniden tahsis edilmesini sağlamak uygun olmayabilir . - Her iş parçacığı kendi özel belleğini ayırabilir ve bozabilir, ancak daha sonra komşu bölgelere endeksleme yapmak daha karmaşıktır. (Seyrek bir matris vektör ürün dikkate matris ve vektörlerinin bir satır, bölüm ile, bir sahipsiz bir kısmını indeksleme x , daha karmaşık veri yapısı gerektirmektedir x . Sanal bellek bitişik değildir)
NUMA tahsisi / başlatmaya yönelik çözümlerin deyimsel olduğu düşünülüyor mu? Diğer kritik gotcha'ları da bıraktım mı?
(C ++ örneklerimin bu dile vurgu yaptığı anlamına gelmez, ancak C ++ dili , C gibi bir dilin yapmadığı bellek yönetimi hakkında bazı kararları kodlar, bu nedenle C ++ programcılarının bunları yapmasını önerirken daha fazla direnç eğilimi farklı şeyler.)