亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

SSE指令:哪些CPU可以執行原子16B內存操作?

SSE指令:哪些CPU可以執行原子16B內存操作?

桃花長相依 2019-10-11 14:37:15
考慮x86 CPU上的單個內存訪問(單個讀取或單個寫入,而不是讀寫)。該指令正在訪問16個字節(128位)的存儲器,并且所訪問的存儲器位置與16個字節對齊。文檔“英特爾?64架構內存訂購白皮書”指出,對于“讀取或寫入地址在8字節邊界上對齊的四字(8字節)的指令”,內存操作似乎作為單個內存訪問執行內存類型。問題:是否存在Intel / AMD / etc x86 CPU,它們保證對16個字節邊界對齊的16個字節(128位)的讀寫操作作為單個內存訪問執行?是的,它是哪種特定類型的CPU(Core2 / Atom / K8 / Phenom / ...)?如果您提供此問題的答案(是/否),請同時指定用于確定答案的方法 -PDF文檔查找,蠻力測試,數學證明或其他用于確定答案的方法。此問題與諸如http://research.swtch.com/2010/02/off-to-races.html的問題有關更新:我用C創建了一個簡單的測試程序,您可以在計算機上運行該程序。請在您的Phenom,Athlon,Bobcat,Core2,Atom,Sandy Bridge或任何具有SSE2功能的CPU上編譯并運行它。謝謝。// Compile with://   gcc -o a a.c -pthread -msse2 -std=c99 -Wall -O2//// Make sure you have at least two physical CPU cores or hyper-threading.#include <pthread.h>#include <emmintrin.h>#include <stdio.h>#include <stdint.h>#include <string.h>typedef int v4si __attribute__ ((vector_size (16)));volatile v4si x;unsigned n1[16] __attribute__((aligned(64)));unsigned n2[16] __attribute__((aligned(64)));void* thread1(void *arg) {        for (int i=0; i<100*1000*1000; i++) {                int mask = _mm_movemask_ps((__m128)x);                n1[mask]++;                x = (v4si){0,0,0,0};        }        return NULL;}void* thread2(void *arg) {        for (int i=0; i<100*1000*1000; i++) {                int mask = _mm_movemask_ps((__m128)x);                n2[mask]++;                x = (v4si){-1,-1,-1,-1};        }        return NULL;}int main() {        // Check memory alignment        if ( (((uintptr_t)&x) & 0x0f) != 0 )                abort();        memset(n1, 0, sizeof(n1));        memset(n2, 0, sizeof(n2));        pthread_t t1, t2;        pthread_create(&t1, NULL, thread1, NULL);        pthread_create(&t2, NULL, thread2, NULL);        pthread_join(t1, NULL);        pthread_join(t2, NULL);        for (unsigned i=0; i<16; i++) {                for (int j=3; j>=0; j--)                        printf("%d", (i>>j)&1);
查看完整描述

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,并且仍然可以重現故障。


查看完整回答
反對 回復 2019-10-11
?
慕妹3242003

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原子操作的書面保證。


查看完整回答
反對 回復 2019-10-11
  • 3 回答
  • 0 關注
  • 1000 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號