2016-08-03 34 views
6

試圖用我的想法去上同時使用軟件和硬件的記憶障礙,我可以禁用外,爲了優化爲與編譯器的優化編譯代碼內部的特定功能的,因此我也使用像PetersonDeker算法需要外的順序沒有執行實現軟件旗語,我已經測試了以下代碼包含兩個SW屏障asm volatile("": : :"memory")和gcc內建HW屏障__sync_synchronize使用內存屏障強制順序執行

#include <stdio.h> 
int main(int argc, char ** argv) 
{ 
    int x=0; 
    asm volatile("": : :"memory"); 
    __sync_synchronize(); 
    x=1; 
    asm volatile("": : :"memory"); 
    __sync_synchronize(); 
    x=2; 
    asm volatile("": : :"memory"); 
    __sync_synchronize(); 
    x=3; 
    printf("%d",x); 
    return 0; 
} 

但是,編譯輸出文件是:

main: 
.LFB24: 
    .cfi_startproc 
    subq $8, %rsp 
    .cfi_def_cfa_offset 16 
    mfence 
    mfence 
    movl $3, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    mfence 
    call __printf_chk 
    xorl %eax, %eax 
    addq $8, %rsp 

如果我消除障礙並重新編譯,我得到:

main 
.LFB24: 
    .cfi_startproc 
    subq $8, %rsp 
    .cfi_def_cfa_offset 16 
    movl $3, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    xorl %eax, %eax 
    addq $8, %rsp 

都在Ubuntu 14.04.1 LTS,86與gcc -Wall -O2編譯。

預期的結果是,包含內存障礙的代碼的輸出文件將包含我在源代碼中的值的所有賦值,其中包含mfence

根據相關的StackOverflow職位 -

gcc memory barrier __sync_synchronize vs asm volatile("": : :"memory")

當在每次迭代增加你的內聯彙編,GCC不允許改變操作的順序,經過阻擋

及以後:

Howe版本,當CPU performes這個代碼,它允許重新排序 操作「引擎蓋下」,只要它不會破壞內存 排序模型。這意味着執行操作可能不按順序完成(如果CPU支持該操作,就像現在大多數操作一樣)。 HW 圍欄會阻止這種情況發生。

但正如你所看到的,與記憶障礙的代碼,並沒有他們的代碼之間的唯一區別在於,前者包含了一個辦法,我不希望看到它mfence,而不是所有的任務被包含在內。

爲什麼與記憶障礙的文件的輸出文件並沒有如我expected-爲什麼mfence順序已經被改變?爲什麼編譯器刪除了一些任務?是否允許編譯器進行優化,即使應用了內存屏障並將每行代碼分開了?

引用到存儲器屏障類型和使用:

+1

術語:**亂序執行獨立於內存重新排序**。即使按順序的CPU也是流水線式的,並且受益於存儲緩衝區,特別是對於L1中錯過的商店。 (https://en.wikipedia.org/wiki/MESI_protocol#Memory_Barriers。一旦它們被認爲不是推測性的,只有通過內存排序邏輯才能對它們進行跟蹤(如果需要,可以強制執行StoreStore和LoadStore排序),直到它們實際上在管道忘記它們之後提交到​​L1緩存。)'MFENCE'不會序列化流水線;它僅序列化內存操作變爲全局可見的順序。 –

回答

4

存儲器障礙告訴編譯器/ CPU該指令不應該跨越障礙重新排序,它們並不意味着無論如何都可以證明無效的寫入。

如果你定義xvolatile,編譯器不能作一個假設,即它是在乎x價值並具有遵循C抽象的機器,這對於存儲器寫入規則的唯一實體實際發生。

在你的具體情況下,你可以跳過障礙,因爲它已經保證了易失性訪問不會相互重排。

如果您有C11支持,您最好使用_Atomic,它還可以保證不會針對您的x重新排序正常分配,並且訪問是原子性的。


編輯:GCC(以及鐺),似乎在這方面的不一致,也不會總是這樣做optimizaton。 I opened a GCC bug report regarding this.

+3

你寫了比我好得多的答案。 – 2501

+0

正確的答案。我已經用'volatile'測試了它,並且帶有內存屏障的代碼按照我的預期進行了編譯(而沒有內存屏障的代碼仍然進行了優化)。不幸的是,我不能測試'atomic',因爲我沒有C11的支持。 – user2162550

+0

@ 2501謝謝。如果您認爲可以改進,請隨意擴展它。 :) – a3f