[英]Should std::atomic<int*>::load be doing a compare-and-swap loop?
簡介 :我原本以為std::atomic<int*>::load
with std::memory_order_relaxed
將接近直接加載指針的性能,至少當加載的值很少改變時。 我看到原子負載的性能遠遠低於Visual Studio C ++ 2012上的正常負載,因此我決定進行調查。 事實證明原子負載是作為比較和交換循環實現的,我懷疑它不是最快的實現。
問題 : std::atomic<int*>::load
需要進行比較和交換循環?
背景 :我相信MSVC ++ 2012正在基於此測試程序對指針的原子加載進行比較和交換循環:
#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;
}
我正在使用__declspec(noinline)
函數來隔離與原子載荷相關的匯編指令。 我做了一個新的MSVC ++ 2012項目,添加了一個x64平台,選擇了發布配置,在調試器中運行程序並查看了反匯編。 事實證明, std::atomic<char>
和std::atomic<int>
參數最終都會對loadRelaxed<int>
進行相同的調用 - 這必須是優化器所做的事情。 這是被調用的兩個loadRelaxed實例的反匯編:
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
是原子比較和交換 ,我們在這里看到原子加載char
, int
或int*
是比較和交換循環。 我還為32位x86構建了這個代碼,並且該實現仍然基於lock cmpxchg
。
問題 : std::atomic<int*>::load
需要進行比較和交換循環?
我不相信放松的原子載荷需要比較和交換。 最后這個std :: atomic實現不能用於我的目的,但我仍然想要接口,所以我使用MSVC的屏障內部函數創建了自己的std :: atomic。 對於我的用例,這比默認的std::atomic
具有更好的性能。 你可以在這里看到代碼。 對於加載和存儲的所有排序,它應該被實現為C ++ 11規范。 Btw GCC 4.6在這方面並不是更好。 我不知道GCC 4.7。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.