簡體   English   中英

SSE _mm_dp_ps 大小結果

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM