繁体   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