AVX2 1x mm256i 32bit 到 2x mm256i 64bit
Posted
技术标签:
【中文标题】AVX2 1x mm256i 32bit 到 2x mm256i 64bit【英文标题】:AVX2 1x mm256i 32bit to 2x mm256i 64bit 【发布时间】:2014-08-07 02:26:52 【问题描述】:有没有一种正常的方法可以将 1x __m256i 的 32 位整数转换为 2x __m256i 的 64 位整数。我正在平均数据,我的 32 位整数溢出。所以我想把累加器寄存器分成两个64位寄存器。
【问题讨论】:
【参考方案1】:作为构建块,您正在寻找 VPMULDQ
指令或 _mm256_mul_epi32 内在函数。
这是 32x32 -> 64 乘法,但与您想要的略有不同。在这种情况下,源ymm
寄存器每个都包含四个 32 位值,并输出到四个 64 位值的单个寄存器。
根据英特尔的文档:
DEST[63:0] ← SRC1[31:0] * SRC2[31:0]
DEST[127:64] ← SRC1[95:64] * SRC2[95:64]
DEST[191:128] ← SRC1[159:128] * SRC2[159:128]
DEST[255:192] ← SRC1[223:192] * SRC2[223:192]
所以要获得 8x32 * 8x32 -> 两个 4x64 寄存器,您需要拆分工作:
void mul32to64(__m256i a, __m256i b, __m256i *reshi, __m256i *reslo)
*reshi = _mm256_mul_epi32(
_mm256_cvtepi32_epi64(_mm256_extracti128_si256(a, 1)),
_mm256_cvtepi32_epi64(_mm256_extracti128_si256(b, 1)));
*reslo = _mm256_mul_epi32(
_mm256_cvtepi32_epi64(_mm256_castsi256_si128(a)),
_mm256_cvtepi32_epi64(_mm256_castsi256_si128(b)));
【讨论】:
这不是有点矫枉过正吗?有一个扩展整数的指令。除非我忽略了某些东西,_mm256_cvtepu32_epi64
表示未签名,_mm256_cvtepi32_epi64
表示已签名?
谢谢,显然对 SSE 太累了。【参考方案2】:
我最终使用了 _mm256_unpackhi_epi32 和 _mm256_unpacklo_epi32,参数 b 的值为 0。这是一个仅执行平均的示例。
#define DATA_SIZE 16
__declspec(align(16)) static int buf[] =
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
;
__m256i zero = 0 ;
__m256i accumulated = 0 ;
for (int idx = 0; idx < DATA_SIZE; idx = idx + 8)
//load data from buf
__m256i int32data = _mm256_load_si256((__m256i*)(buf + idx));
__m256i data2 = _mm256_unpackhi_epi32(int32data, zero); //extract 4 ints
__m256i data3 = _mm256_unpacklo_epi32(int32data, zero); //extract 4 more
accumulated = _mm256_add_epi64(accumulated, data2); //accumulate first 4
accumulated = _mm256_add_epi64(accumulated, data3); //accumulate 2nd 4
__m256i averageVec;
_mm256_store_si256(&averageVec, accumulated); //unload accumulated vector
//calculate the average
long long average = (averageVec.m256i_i64[0] + averageVec.m256i_i64[1]
+ averageVec.m256i_i64[2] + averageVec.m256i_i64[3])
/ DATA_SIZE;
printf("Average is: %d\n", average);
【讨论】:
请注意,您的平均计算是不可移植的 - 它仅适用于 Visual C(因此仅适用于 Windows),这可能适合您的应用程序,但如果您应该注意这一点对编写跨平台代码感兴趣。 你的意思是我使用的是 long long 而不是 __int64? 确实应该是标准类型的可移植性(int64_t
- long long
和 __int64
都不是可移植的),但我指的是使用 .m256i_i64[n]
,是微软主义。以上是关于AVX2 1x mm256i 32bit 到 2x mm256i 64bit的主要内容,如果未能解决你的问题,请参考以下文章
将 2x4 64b 结构的第一行加载到 AVX2 的 256b 寄存器中的最快方法是啥?