在这个小代码示例中:
__m128i twos = _mm_set_epi32(2,3,1,2);
__m128i foo = _mm_set_epi32(128,128,128,128);
__m128i shifted = _mm_srl_epi32(foo,twos);
“移位”充满了零,而我希望它两个充满四个 32 位整数,其值分别为 32、16、64 和 32。我是否使用了内在错误?
在这个小代码示例中:
__m128i twos = _mm_set_epi32(2,3,1,2);
__m128i foo = _mm_set_epi32(128,128,128,128);
__m128i shifted = _mm_srl_epi32(foo,twos);
“移位”充满了零,而我希望它两个充满四个 32 位整数,其值分别为 32、16、64 和 32。我是否使用了内在错误?
是的,您使用不正确。的第二个参数_mm_srl_epi32()
指定将第一个参数移动的位数,但它不是您可能期望的矢量参数,允许您将每个 32 位整数移动不同的位数。而是将 128 位参数截断为 64 位,并使用所得计数来确定要移位的位数;第一个参数中的所有 4 个整数使用相同的移位量。在您的情况下,较低的 64 位是0x0000000100000010
,它的计算结果是一个非常大的正数。这导致所有元素都foo
被刷新为零,因为所有位都被移出。
英特尔的AVX Programmer's Reference是查找每条指令的所有小细节的好地方。虽然标题可能有点用词不当,但该文档包含所有 SSE/SSE2/.../AVX/AVX2 指令的描述以及英特尔 C++ 编译器中可用的内在函数的描述(通常也可用于gcc
和其他)。在文档中搜索可以_mm_srl_epi32
清楚地解释该指令的确切作用。