3 回答

TA貢獻1802條經驗 獲得超10個贊
在《英特爾?64和IA-32架構開發人員手冊》中。3A如今包含您提到的內存訂購白皮書的規格,在第8.2.3.1節中說,正如您自己指出的那樣,
Intel-64內存排序模型可確保以下各項
內存訪問指令,似乎要執行組成內存操作
作為單個內存訪問:
?讀取或寫入單個字節的指令。
?讀取或寫入地址(2字節)對齊的字(2個字節)的指令
字節邊界。
?讀取或寫入地址對齊的雙字(4個字節)的指令
在4個字節的邊界上。
?讀取或寫入地址對齊在其上的四字(8字節)的指令
8字節邊界。
任何鎖定的指令(XCHG指令或其他讀-修改-寫
帶有LOCK前綴的指令)似乎作為不可分割的和
不間斷的裝載順序,然后是存儲順序,與對齊方式無關。
現在,由于上面的列表不包含雙四字(16字節)的相同語言,因此該體系結構不保證訪問16字節內存的指令是原子的。
話雖如此,最后一段確實暗示了一條出路,即帶有LOCK前綴的CMPXCHG16B指令。您可以使用CPUID指令確定處理器是否支持CMPXCHG16B(“ CX16”功能位)。
在相應的AMD文檔《AMD64技術AMD64體系結構程序員手冊》第2卷:系統編程中,我找不到相似的清晰語言。
編輯:測試程序結果
(修改了測試程序,使#迭代次數增加了10倍)
在Xeon X3450(x86-64)上:
0000 999998139 1572
0001 0 0
0010 0 0
0011 0 0
0100 0 0
0101 0 0
0110 0 0
0111 0 0
1000 0 0
1001 0 0
1010 0 0
1011 0 0
1100 0 0
1101 0 0
1110 0 0
1111 1861 999998428
在Xeon 5150(32位)上:
0000 999243100 283087
0001 0 0
0010 0 0
0011 0 0
0100 0 0
0101 0 0
0110 0 0
0111 0 0
1000 0 0
1001 0 0
1010 0 0
1011 0 0
1100 0 0
1101 0 0
1110 0 0
1111 756900 999716913
在Opteron 2435(x86-64)上:
0000 999995893 1901
0001 0 0
0010 0 0
0011 0 0
0100 0 0
0101 0 0
0110 0 0
0111 0 0
1000 0 0
1001 0 0
1010 0 0
1011 0 0
1100 0 0
1101 0 0
1110 0 0
1111 4107 999998099
這是否意味著Intel和/或AMD保證16字節內存訪問在這些計算機上是原子的?恕我直言,事實并非如此。它不在文檔中作為保證的體系結構行為,因此無法知道在這些特定處理器上16字節內存訪問是否確實是原子的,或者測試程序是否僅由于某種原因未能觸發它們。因此依靠它是危險的。
編輯2:如何使測試程序失敗
哈!我設法使測試程序失敗。在與上述相同的Opteron 2435上,具有相同的二進制文件,但是現在通過“ numactl”工具運行它,指定每個線程在單獨的套接字上運行,我得到:
0000 999998634 5990
0001 0 0
0010 0 0
0011 0 0
0100 0 0
0101 0 0
0110 0 0
0111 0 0
1000 0 0
1001 0 0
1010 0 0
1011 0 0
1100 0 1不是單個內存訪問!
1101 0 0
1110 0 0
1111 1366 999994009
那么,這意味著什么呢?好吧,Opteron 2435可以保證也可以不保證16字節內存訪問對于套接字內訪問是原子的,但是至少在兩個套接字之間的HyperTransport互連上運行的緩存一致性協議不能提供這種保證。
編輯3:應“ GJ”請求,用于線程功能的ASM。
這是為Opteron 2435系統上使用的GCC 4.4 x86-64版本的線程函數生成的asm:
.globl thread2
.type thread2, @function
thread2:
.LFB537:
.cfi_startproc
movdqa .LC3(%rip), %xmm1
xorl %eax, %eax
.p2align 5,,24
.p2align 3
.L11:
movaps x(%rip), %xmm0
incl %eax
movaps %xmm1, x(%rip)
movmskps %xmm0, %edx
movslq %edx, %rdx
incl n2(,%rdx,4)
cmpl $1000000000, %eax
jne .L11
xorl %eax, %eax
ret
.cfi_endproc
.LFE537:
.size thread2, .-thread2
.p2align 5,,31
.globl thread1
.type thread1, @function
thread1:
.LFB536:
.cfi_startproc
pxor %xmm1, %xmm1
xorl %eax, %eax
.p2align 5,,24
.p2align 3
.L15:
movaps x(%rip), %xmm0
incl %eax
movaps %xmm1, x(%rip)
movmskps %xmm0, %edx
movslq %edx, %rdx
incl n1(,%rdx,4)
cmpl $1000000000, %eax
jne .L15
xorl %eax, %eax
ret
.cfi_endproc
為了完整起見,.LC3是包含thread2使用的(-1,-1,-1,-1)向量的靜態數據:
.LC3:
.long -1
.long -1
.long -1
.long -1
.ident "GCC: (GNU) 4.4.4 20100726 (Red Hat 4.4.4-13)"
.section .note.GNU-stack,"",@progbits
另請注意,這是AT&T ASM語法,而不是Windows程序員可能更熟悉的Intel語法。最后,這是進行曲=本機,這使GCC更喜歡MOVAPS;但這沒關系,如果我使用march = core2,它將使用MOVDQA來存儲到x,并且仍然可以重現故障。

TA貢獻1824條經驗 獲得超6個贊
的“AMD架構程序員手冊卷1:應用程序編程”表示在節3.9.1:“ CMPXCHG16B可被用來執行在64位模式的16字節的原子訪問(與某些對齊限制)”。
但是,沒有關于SSE指令的評論。實際上,在4.8.3中有一條注釋,即LOCK前綴“與128位媒體指令一起使用時會導致無效操作碼異?!薄R虼?,在我看來,AMD處理器不能保證對SSE指令進行原子128位訪問是完全結論性的,并且進行原子128位訪問的唯一方法是使用CMPXCHG16B。
“ 英特爾64和IA-32體系結構軟件開發人員手冊第3A卷:系統編程指南,第1部分 ”在8.1.1中說:“可以使用多次內存訪問來實現訪問大于四字的數據的x87指令或SSE指令。 ” 這是非常確定的,ISA不能保證128位SSE指令是原子的。 英特爾文檔的第2A卷說CMPXCHG16B:“此指令可以與LOCK前綴一起使用,以允許原子執行該指令。”
此外,在這種情況下,CPU制造商尚未發布針對特定CPU型號的128b SSE原子操作的書面保證。
- 3 回答
- 0 關注
- 1000 瀏覽
添加回答
舉報