簡體   English   中英

使用AVX指令和-O3編譯選項獲得錯誤的結果

[英]Getting wrong results with using AVX instructions and -O3 compiling option

我用AVX指令編寫了非常簡單的程序,但是當我使用-O3選項編譯代碼和g ++編譯器的-O1選項時,我得到的結果不同,這是我的代碼:

int main(int argc, char *argv[])
{

    int d = 120;
    __m256i r = _mm256_set1_epi32(d);
    int * p = (int *) &r;

    printf("r[0]: %d, ",p[0]);
    printf("r[1]: %d, ",p[1]);
    printf("r[2]: %d, ",p[2]);
    printf("r[3]: %d, ",p[3]);
    printf("r[4]: %d, ",p[4]);
    printf("r[5]: %d, ",p[5]);
    printf("r[6]: %d, ",p[6]);
    printf("r[7]: %d \n",p[7]);                    

    return 0;
}

這是我使用這些選項編譯時的輸出(g ++ test1.c -o test1 -m64 -O3 -ffast-math -march = native -mavx):

r [0]:0,r [1]:0,r [2]:4195520,r [3]:0,r [4]: - 1880829792,r [5]:32767,r [6]:0, r [7]:0

這是我用這些選項編譯時的輸出(g ++ test1.c -o test1 -m64 -O1 -ffast-math -march = native -mavx):

r [0]:120,r [1]:120,r [2]:120,r [3]:120,r [4]:120,r [5]:120,r [6]:120,r [7]:120

第二個結果(-O1)是正確的,但第一個是錯誤的。 我不知道為什么會這樣。

禁用嚴格別名會降低整個程序的性能!

Casting &r to (int*)沒有定義的行為。 __m256i r是一個固有的AVX寄存器,不一定映射到內存。 通過獲取指針,可以強制編譯器將其寫入內存,並且最終可能會將其映射到int [8]向量。

它可能適用於某些編譯器,有些選項,在某些情況下也適用。 但是,您不應該在代碼中使用它,因為它可能會停止工作而不會發出警告。

“定義行為”的方式是:

int[8] p;
_mm256_storeu_si128((__m256i*)p, r);
printf("r[0]: %d, ",p[0]);
printf("r[1]: %d, ",p[1]);
printf("r[2]: %d, ",p[2]);
printf("r[3]: %d, ",p[3]);
printf("r[4]: %d, ",p[4]);
printf("r[5]: %d, ",p[5]);
printf("r[6]: %d, ",p[6]);
printf("r[7]: %d \n",p[7]); 

然后你明確地將寄存器寫入內存。 這將做同樣的事情,但無論編譯器選項如何都將始終有效。 由於禁用嚴格別名會降低整體代碼優化,因此整個程序運行速度更快。

我剛看了你的評論說你已經解決了問題,但在搜索引擎上它仍然顯示為“沒有答案”,這對於有類似問題的人來說有點誤導。 這里的原始答案實際上是錯誤的,但原始海報還沒有改變正確的答案,所以我會更新這個。

簡短的回答是,cast &r to (int*)沒有定義的行為。 有關更多詳細信息,請參閱galinette的答案。

定義的行為方式是將寄存器顯式寫入內存:

int[8] p;
_mm256_storeu_si128((__m256i*)p, r);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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