Visual Studio C编译器或Intel Intrinsics的AVX2"_mm256_set_epi64x"函数中的潜在错误

oPo*_*olo 7 c++ intrinsics avx visual-studio compiler-bug

我对AVX2功能上的英特尔Intrinsics有一个非常奇怪的错误,我想在这里分享.不管是我做错了什么(我现在还不能看到什么),或者库中的错误.

我在main.c中有这个简单的代码:

__int64 test = 0xFFFF'FFFF'FFFF'FFFF;
__m256i ymm = _mm256_set_epi64x(0x0000'0000'0000'0000,
                                0x0000'0000'0000'0000, 
                                0x0000'0000'0000'0000, 
                                test);
Run Code Online (Sandbox Code Playgroud)

赋给变量ymm的值是出于某种奇怪的原因:

ymm.m256i_i64[0] = 0xffff'ffff'ffff'ffff
ymm.m256i_i64[1] = 0x0000'0000'0000'0000
ymm.m256i_i64[2] = 0x0000'ffff'0000'0000
ymm.m256i_i64[3] = 0x0000'0000'0000'0000
Run Code Online (Sandbox Code Playgroud)

此时我已经调试了好几个小时,但看不出为什么ymm.m256i_i64[2]会得到这个流氓价值.请帮忙!

有趣/奇怪的事实: 如果我写这个C代码:

__m256i ymm = _mm256_set_epi64x(0x0000'0000'0000'0000,
                                0x0000'0000'0000'0000, 
                                0x0000'0000'0000'0000, 
                                0xFFFF'FFFF'FFFF'FFFF);
Run Code Online (Sandbox Code Playgroud)

然后将值正确设置为:

ymm.m256i_i64[0] = 0xffff'ffff'ffff'ffff
ymm.m256i_i64[1] = 0x0000'0000'0000'0000
ymm.m256i_i64[2] = 0x0000'0000'0000'0000
ymm.m256i_i64[3] = 0x0000'0000'0000'0000
Run Code Online (Sandbox Code Playgroud)

注意:我使用的是Visual Studio; 他们的编译器和调试工具,如下图所示: 在此输入图像描述

打印代码后的printf : ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 ff ff ff 00 ff ff 00 00 ff 00 00 00 ff 00 00 00.

似乎结构中其他变量的流氓变化可以改变,因为在我添加循环之后它们不一样,因为它们之前......(我不知道循环是否特意进行了更改).

编辑:我不是集会的鹰派......根本没有.我在下面的图片中添加了生成的汇编代码,以防任何人帮助我了解正在发生的事情,以及它是否是由我造成的错误: 在此输入图像描述

Z b*_*son 5

直到最近,MSVC 还不支持epi64x32 位模式下的任何内在函数。他在 Agner Fog 的VCL库中写道

//#if defined (_MSC_VER) && _MSC_VER < 1900 && ! defined (__x86_64__) && ! defined(__INTEL_COMPILER)
// MS compiler cannot use _mm256_set1_epi64x in 32 bit mode, and  
// cannot put 64-bit values into xmm register without using
// mmx registers, and it makes no emms
Run Code Online (Sandbox Code Playgroud)

要使用 MSVC 在 32 位模式下解决此问题,您可以执行以下操作:

union {
    int64_t q[4];
    int32_t r[8];
} u;
u.q[0] = a; u.q[1] = b; u.q[2] = c; u.q[3] = d;
_mm256_setr_epi32(u.r[0], u.r[1], u.r[2], u.r[3], u.r[4], u.r[5], u.r[6], u.r[7]);
Run Code Online (Sandbox Code Playgroud)

或者使用 64 位模式。

  • 回复晚了,抱歉……那是压力很大的几个月。我正在写论文,幸运的是,结果很好。不管我的回答迟到了,你的帖子帮助我发现了我认为是一个错误,这个错误可能会花费我几个小时(如果不是一两天)在我的论文期间进行故障排除。值得深表感谢:非常感谢您的帮助! (2认同)