我一直在使用gcc的Intel兼容的內置命令(如__sync_fetch_and_add
)很長一段時間,用自己的atomic
模板。 「__sync
」功能現在正式被認爲是「遺留」。爲什麼GCC std :: atomic increment會生成低效的非原子組裝?
C++ 11支持std::atomic<>
及其後代,所以它似乎是合理的使用,而不是,因爲它使我的代碼符合標準,編譯器會產生最好的代碼無論哪種方式,獨立於平臺的方式,也就是幾乎太好了,不可能是真的。
順便說一句,我只與std::atomic
文本替換atomic
了。 std::atomic
(re:內存模型)中有很多我並不真正需要的,但是默認參數可以解決這個問題。
現在的壞消息。事實證明,從我所知道的情況來看,生成的代碼......完全是廢話,甚至根本不是原子。即使是增加一個單個原子變量並將其輸出具有最小的例子沒有少於5個非內聯函數調用以___atomic_flag_for_address
,___atomic_flag_wait_explicit
,和__atomic_flag_clear_explicit
(完全優化),並且在另一方面,沒有在一個單一的原子指令生成可執
什麼給?當然總是有編譯器錯誤的可能性,但是對於大量的審閱者和用戶來說,這些相當激烈的事情通常不會被忽視。這意味着,這可能不是一個錯誤,而是預期的行爲。
什麼是「合理」的背後這麼多的函數調用,以及如何實現原子不原子?
AS-簡單-AS-它可任意得到例如:
#include <atomic>
int main()
{
std::atomic_int a(5);
++a;
__builtin_printf("%d", (int)a);
return 0;
}
產生以下.s
:
movl $5, 28(%esp) #, a._M_i
movl %eax, (%esp) # tmp64,
call ___atomic_flag_for_address #
movl $5, 4(%esp) #,
movl %eax, %ebx #, __g
movl %eax, (%esp) # __g,
call ___atomic_flag_wait_explicit #
movl %ebx, (%esp) # __g,
addl $1, 28(%esp) #, MEM[(__i_type *)&a]
movl $5, 4(%esp) #,
call _atomic_flag_clear_explicit #
movl %ebx, (%esp) # __g,
movl $5, 4(%esp) #,
call ___atomic_flag_wait_explicit #
movl 28(%esp), %esi # MEM[(const __i_type *)&a], __r
movl %ebx, (%esp) # __g,
movl $5, 4(%esp) #,
call _atomic_flag_clear_explicit #
movl $LC0, (%esp) #,
movl %esi, 4(%esp) # __r,
call _printf #
(...)
.def ___atomic_flag_for_address; .scl 2; .type 32; .endef
.def ___atomic_flag_wait_explicit; .scl 2; .type 32; .endef
.def _atomic_flag_clear_explicit; .scl 2; .type 32; .endef
...和所提到的函數看起來例如像這樣在objdump
:
004013c4 <__atomic_flag_for_address>:
mov 0x4(%esp),%edx
mov %edx,%ecx
shr $0x2,%ecx
mov %edx,%eax
shl $0x4,%eax
add %ecx,%eax
add %edx,%eax
mov %eax,%ecx
shr $0x7,%ecx
mov %eax,%edx
shl $0x5,%edx
add %ecx,%edx
add %edx,%eax
mov %eax,%edx
shr $0x11,%edx
add %edx,%eax
and $0xf,%eax
add $0x405020,%eax
ret
其餘的是有些簡單,但我沒有找到一個單一的指令,將真正是原子的(除一些虛假xchg
其他哪些是的X86原子,但這些似乎相當於NOP /填充,因爲它是xchg %ax,%ax
,跟在ret
之後)。
我絕對不知道什麼是需要這樣一個相當複雜的功能,以及它是如何打算做什麼原子。
你使用的是什麼版本的GCC?你能否展示一個導致這種糟糕代碼的小程序?我正在運行上個月的4.7快照,它似乎產生了不錯的代碼,並帶有'lock'指令。 –
作爲一個可能的罪魁禍首,你會想到你「不需要」的記憶模型。你的代碼是什麼樣的?你最後一句話的含義是什麼:「原子性如何在沒有原子性的情況下實現」? – jalf
「內存模型」,你的意思是「內存排序」? –