[英]SSE _mm_dp_ps size result
我開始使用 SSE 進行操作。 我想用_mm_dp_ps
制作兩個點積,並將第一個結果保存在aux_sse
,將第二個結果保存在aux_sse
。 B 是值為 1 的 8 元素向量。
由於每對只需要兩個浮點數,因此我做了以下代碼:
printf("A \n");
for(i = 0; i < M; i++){
for(j = 0; j < ele; j++){
A[i*ele+j] = i*ele+j;
printf(" %f ", A[i*ele+j]);
}
printf("\n");
}
float aux[ele*M];
float aux2[ele*M];
__m128 *A_sse = (__m128*) A;
__m128 *B_sse = (__m128*) B;
__m128 *aux_sse = (__m128*) aux;
__m128 *aux2_sse = (__m128*) aux2;
for(int i = 0; i < M; i++)
{
*aux_sse = _mm_dp_ps (*A_sse, *B_sse, 0xFF);
printf("%f \n", aux[i]);
B_sse ++;
A_sse++;
*aux2_sse = _mm_dp_ps (*A_sse, *B_sse, 0xFF);
printf("%f \n", aux2[i]);
B_sse --;
A_sse ++;
aux_sse+= sizeof(char);
aux2_sse+= sizeof(char);
}
我得到以下錯誤輸出:
A
0.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000
8.000000 9.000000 10.000000 11.000000 12.000000 13.000000 14.000000 15.000000
6.000000
22.000000
6.000000
22.000000
根據這個:
使用 imm8 中的高 4 位將 a 和 b 中的壓縮單精度(32 位)浮點元素有條件地相乘,對四個乘積求和,並使用 imm8 的低 4 位有條件地將和存儲在 dst 中。
我知道在 imm8 中我們在元素中指定要保存結果的元素。
據我了解,即使結果在輸出向量的 4 個元素中,如果我只使用aux_sse+= sizeof(char)
增加一個元素,結果應該被覆蓋,並且會出現所需的結果。 但是,我看到情況並非如此。
如果我在打印 aux 和 aux2 的結果時進行以下修改,則輸出是正確的。
printf("%f \n", aux[i*4]);
printf("%f \n", aux2[i*4]);
輸出:
6.000000
22.000000
38.000000
54.000000
我正在使用 gcc 編譯器。 有誰知道問題是什么? 任何答案都會有所幫助。
編輯:
我需要 aux 和 aux2 的元素來對應每次迭代:
aux[i] = dot_product 在迭代 i 中執行
aux_sse+= sizeof(char);
是一種寫aux_sse+=1
的荒謬方式,即前進 16 個字節,也就是 4 個浮點數,即sizeof(__m128) == sizeof(*aux_sse) == 16
。
因此,如果您還通過浮點索引訪問數組,是的,如果您只為每個包含 4 個浮點數的向量將i
增加 1,則必須將其縮放 4。
通常使用_mm_store_ps(&aux[i], v);
更容易_mm_store_ps(&aux[i], v);
而不是跟蹤__m128*
變量來訪問相同的數組。 並且做i+=4
所以i
實際上是在索引你擁有的 4 元素組的開始,而不是需要縮放它。 這使得編寫像i < M-3
這樣的循環邊界變得更容易。
另請注意,您應該使用alignas(16) float aux[ele*M];
如果您想對數組進行需要對齊的訪問。 GCC 會注意到您在做什么,並會在它可以看到數組的使用方式時為您對齊數組,但通常不要指望它。
或者您是否只想存儲單個float
結果,而不是為每組 4 個輸入存儲4 個相同的點積? 在這種情況下,您應該提取低標量元素,例如_mm_store_ss (&aux[i], v)
。 或_mm_cvtss_f32(v)
將向量的低元素作為標量float
。
如果需要,您可以手動執行四個 4 元素點積,生成 1 個包含 4 個結果的向量。 _mm_mul_ps
然后可能是 2x _mm_hadd_ps
(SSE3) 水平減少,一種轉置和添加。 (由@mainactual 推薦)
dpps
在 Skylake 和類似的 Intel CPU ( https://uops.info ) 上是 4 dpps
,所以如果你有多個點積要做,那就不好了。
為了避免 SSE3,您可以使用_mm_shuffle_ps
( shufps ) 從 2 個向量中選取元素,或者一些_mm_unpacklo_ps
/ unpackhi 可能有用,或者pd
版本可以將元素對保持在一起。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.