Özet: std::memory_order_relaxed
ile std::atomic<int*>::load
'un, en azından yüklenen değer nadiren değiştiğinde, doğrudan bir işaretleyicinin yüklenmesi performansına yakın olması beklenirdi. Atomik yük için Visual Studio C++ 2012'deki normal yükten çok daha kötü performans gördüm, bu yüzden araştırmaya karar verdim. Atom yükünün, mümkün olan en hızlı uygulama olmadığını santığım bir compare-and-swap döngü olarak uygulandığı ortaya çıkıyor.std :: atomic <int*> olmalıdır ?: bir karşılaştırma ve takas döngüsü yapmak mı?
Soru: std::atomic<int*>::load
'un bir karşılaştırma ve takas döngüsü yapması için bir neden var mı?
Arkaplan:
#include <atomic>
#include <iostream>
template<class T>
__declspec(noinline) T loadRelaxed(const std::atomic<T>& t) {
return t.load(std::memory_order_relaxed);
}
int main() {
int i = 42;
char c = 42;
std::atomic<int*> ptr(&i);
std::atomic<int> integer;
std::atomic<char> character;
std::cout
<< *loadRelaxed(ptr) << ' '
<< loadRelaxed(integer) << ' '
<< loadRelaxed(character) << std::endl;
return 0;
}
ben amacıyla bir __declspec(noinline)
işlevi kullanıyorum: Ben ++ 2012 MSVC bu test programı dayalı bir işaretçi atomik yük bir karşılaştırma ve takas döngü yapıyor inanıyoruz atomik yük ile ilgili montaj talimatlarını ayırmak için. Yeni bir MSVC++ 2012 projesi yaptım, bir x64 platformu ekledim, sürüm konfigürasyonunu seçtim, programı hata ayıklayıcısında çalıştırdım ve söküme baktım. std::atomic<char>
ve std::atomic<int>
parametrelerinin aynı aramayı loadRelaxed<int>
aynı aramayı verdiğini ortaya çıkarır - bu, optimize edicinin yaptığı bir şey olmalıdır.
loadRelaxed<int * __ptr64>
000000013F4B1790 prefetchw [rcx]
000000013F4B1793 mov rax,qword ptr [rcx]
000000013F4B1796 mov rdx,rax
000000013F4B1799 lock cmpxchg qword ptr [rcx],rdx
000000013F4B179E jne loadRelaxed<int * __ptr64>+6h (013F4B1796h)
loadRelaxed<int>
000000013F3F1940 prefetchw [rcx]
000000013F3F1943 mov eax,dword ptr [rcx]
000000013F3F1945 mov edx,eax
000000013F3F1947 lock cmpxchg dword ptr [rcx],edx
000000013F3F194B jne loadRelaxed<int>+5h (013F3F1945h)
lock cmpxchg
atomik olduğu talimat compare-and-swap ve kod burada bakın: Burada denilen olsun iki loadRelaxed başka örneklerinin sökme İşte bir char
, biratomunun yüklenmesi içinveya bir int*
, bir karşılaştırma ve takas döngüsüdür. Ayrıca bu kodu 32 bit x86 için oluşturdum ve bu uygulama hala lock cmpxchg
'a dayanıyor.
Soru: std::atomic<int*>::load
'un bir karşılaştırma ve takas döngüsü yapması için bir neden var mı?
Bu tür bir kodun neden oluşturulduğunu da görmek isterim – James
@James MS'in henüz bunu daha iyi uygulama zamanı olmadığından şüphe ediyorum. Kendi uygulama çabalarımdan, bunu daha hızlı yapmak için çok az miktarda kod aldı, ancak bu kodun ne yapması gerektiği ve bunun belirli bir donanım platformuyla nasıl etkileştiği ayrıntılı olarak anlamak için büyük çaba harcadı. Diğer insanlar tarafından yazılan materyale bağlı kaldım, ama * gerçekten doğru bir şekilde yaptığınızdan emin olmak için, donanım satıcılarına başvurmanın ve standart üzerinde çok fazla zaman ayırmanın gerekli olacağını düşünüyorum. Karşılaştırma ve takas yapmak çok daha kolay ve kesinlikle doğru. –
Bkz. Http://connect.microsoft.com/VisualStudio/geribildirim/ayrıntılar/770885/STD-atom-yük uygulama-is-saçma-yavaş –