試圖用我的想法去上同時使用軟件和硬件的記憶障礙,我可以禁用外,爲了優化爲與編譯器的優化編譯代碼內部的特定功能的,因此我也使用像Peterson
或Deker
算法需要外的順序沒有執行實現軟件旗語,我已經測試了以下代碼包含兩個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
順序已經被改變?爲什麼編譯器刪除了一些任務?是否允許編譯器進行優化,即使應用了內存屏障並將每行代碼分開了?
引用到存儲器屏障類型和使用:
術語:**亂序執行獨立於內存重新排序**。即使按順序的CPU也是流水線式的,並且受益於存儲緩衝區,特別是對於L1中錯過的商店。 (https://en.wikipedia.org/wiki/MESI_protocol#Memory_Barriers。一旦它們被認爲不是推測性的,只有通過內存排序邏輯才能對它們進行跟蹤(如果需要,可以強制執行StoreStore和LoadStore排序),直到它們實際上在管道忘記它們之後提交到L1緩存。)'MFENCE'不會序列化流水線;它僅序列化內存操作變爲全局可見的順序。 –