簡體   English   中英

C / C ++:放松的std :: atomic <bool> VS X64體系結構上的解鎖布爾

[英]C/C++: relaxed std::atomic<bool> vs unlocked bool on X64 architecture

使用解鎖的布爾值比使用std::atomic<bool>的操作總是在寬松的內存順序下完成有效率嗎? 我認為兩者最終都可以編譯為同一機器代碼,因為單個字節實際上在X64硬件上是原子的。 我錯了嗎?

是的,有潛在的巨大優勢,特別是對於局部變量或在同一函數中重復使用的任何變量。 無法將atomic<>變量優化到寄存器中。

如果您不進行優化而進行編譯,則代碼生成將是相似的,但是在啟用常規優化的情況下進行編譯可能會有巨大的差異。 未優化的代碼類似於使每個變量都是volatile


當前的編譯器也永遠不會將對atomic變量的多次讀取合並為一個,就像您使用了volatile atomic<T> ,因為這是人們所期望的,關於如何允許有用的優化同時禁止您不進行的優化尚未塵埃落定。 “不想 為什么編譯器不合並多余的std :: atomic寫?以及編譯器是否可以優化兩個原子負載? )。

這不是一個很好的例子,但是可以想象一下,檢查布爾值是在一個內聯函數內完成的,並且循環內還有其他內容。 (否則,您將if像普通人一樣繞圈。)

int sumarr_atomic(int arr[]) {
    int sum = 0;
    for(int i=0 ; i<10000 ; i++) {
        if (atomic_bool.load (std::memory_order_relaxed)) {
            sum += arr[i];
        }
    }
    return sum;
}

請參閱Godbolt上的asm輸出

但是使用非原子bool ,編譯器可以通過提升負載來進行轉換,然后自動向量化簡單的求和循環(或根本不運行它)。

使用atomic_bool不能。 使用atomic_bool,asm循環與C ++源代碼非常相似,實際上是在每次循環迭代內對變量的值進行測試和分支。 當然,這會挫敗自動矢量化。

(C ++的假設規則將允許編譯器提升負載,因為它很輕松,因此可以使用非原子訪問進行重新排序。並且合並是因為每次讀取相同的值是讀取一個值的全局指令的一種可能結果。但是正如我所說,編譯器不會這樣做。)


bool數組上的循環可以自動矢量化,但不能自動進行atomic<bool> []循環。


同樣,將類似b ^= 1;的布爾值求反b ^= 1; b++可以只是常規RMW,而不是原子RMW,因此它不必使用lock xorlock btc (x86原子RMW只能通過順序一致性與運行時重新排序來實現,即lock前綴也是一個完整的內存屏障。)

修改非原子布爾值的代碼可以優化實際的修改,例如

void loop() {
    for(int i=0 ; i<10000 ; i++) {
        regular_bool ^= 1;
    }
}

編譯為將regular_bool保存在寄存器中的asm。 不幸的是,它並沒有優化為零(之所以如此,可能是因為對布爾值進行偶次翻轉會將其恢復為原始值)。 但是使用更智能的編譯器也可以。

loop():
    movzx   edx, BYTE PTR regular_bool[rip]   # load into a register
    mov     eax, 10000
.L17:                     # do {
    xor     edx, 1          # flip the boolean
    sub     eax, 1
    jne     .L17          # } while(--i);
    mov     BYTE PTR regular_bool[rip], dl    # store back the result
    ret

即使寫成atomic_b.store( !atomic_b.load(mo_relaxed), mo_relaxed) (單獨的原子加載/存儲),您仍然會在循環中獲得存儲/重載,從而創建了一個6循環的循環依賴鏈存儲/重載(在具有5周期存儲轉發延遲的Intel CPU上),而不是通過寄存器的1周期dep鏈。

Godbolt進行檢查,加載常規的boolstd::atomic<bool>生成不同的代碼,盡管不是因為同步問題。 相反,編譯器(gcc)似乎不願意假設std::atomic<bool>保證為0或1。這很奇怪。

盡管生成的代碼在細節上略有不同,但Clang所做的事情也一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM