2016-05-29 58 views
7

我在AVX2函数中遇到了Intel Intrinsics的一个非常奇怪的错误,我想在此分享它。要么是我做错了什么(我不明白这是什么),或者是图书馆里的一个错误。Visual Studio C编译器或Intel Intrinsics的AVX2“_mm256_set_epi64x”函数中的潜在错误

我有我的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); 

是被分配到青运变量的值是一些奇怪的原因:

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 

我在调试了几个小时这一点,但不明白为什么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); 

随后这些值被正确设置为:

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 

注:我使用Visual Studio;他们的编译器和他们的调试工具,如下图所示: enter image description here

下面的printf 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

看来,结构中其他变量的流氓变化可能会改变,因为它们在添加循环之后不一样,就像以前一样...(我不知道该循环是否特别制作改变)。

编辑:我不是鹰......汇编....根本不是。我在下面的图片,虽然增加了生成的汇编代码,如果它可以帮助任何人来帮助我了解发生了什么事情,如果它是不是由我引起的错误: enter image description here

+1

“库中的Bug”对于仅仅是一个薄包装的内在而言不太可能。你如何检查结果? (Bug可能在那里)。生成的程序集是什么? – MSalters

+0

是的。我在赋值之后添加一个断点,并检查__m256i结构的值,这看起来是错误的。为了清晰起见,我在原始帖子中添加了一张图片。 – oPolo

+1

确实看起来很奇怪。我不会立即排除可视化器中的错误;这比_far_组件映射更复杂。 – MSalters

回答

4

MSVC until recently did not support any of the epi64x intrinsics in 32-bit mode。在昂纳雾的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 

若要解决此在32位模式与MSVC,你可以这样做:

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]); 

或者使用64位模式。

+1

最后回答,对不起...这是一些有压力的月份。我正在撰写我的论文,幸运的是,结果很好。无论我的答案是否迟到,您的文章都帮助我发现了我认为的错误,这些错误在我的论文中可能会花费我几个小时(如果不是一两天)的故障排除。值得非常感谢:非常感谢您的帮助! – oPolo