矢量化:乘 _m256i 元素

Posted

技术标签:

【中文标题】矢量化:乘 _m256i 元素【英文标题】:vectorization : multiply _m256i elements 【发布时间】:2018-01-22 08:24:56 【问题描述】:

我希望使用 SIMD 指令一次将寄存器中的所有 32 位整数相乘,这是我迄今为止尝试过的:

  int32_t a [8] = 1, 2, 3, 4, 5, 6, 7, 8;
  int32_t b [8] = 1, 2, 3, 4, 5, 6, 7, 8;
  __m256i tmp1 = _mm256_loadu_si256((__m256i*) a);
  __m256i tmp2 = _mm256_loadu_si256((__m256i*) b);

  __m256 tmp3 = _mm256_mul_epi32(tmp1,tmp2);

遗憾的是它没有产生正确的结果,这基本上是我得到的: 1、0、9、0、25、0、49、0

我还没有找到替代说明,我们将不胜感激。

【问题讨论】:

【参考方案1】:

如果您使用_mm256_mul_epi32 乘以 32 位整数,您将得到 64 位输出。 _mm256_mul_epi32 工作原理如下

a[0] * b[0] = tmp3[1:0]    1 * 1 = 1
a[2] * b[2] = tmp3[3:2]    3 * 3 = 9
a[4] * b[4] = tmp3[5:4]    5 * 5 = 25
a[6] * b[6] = tmp3[7:6]    7 * 7 = 49

tmp3 中有 4 个结果。

您可以尝试使用_mm256_mullo_epi32,该指令将a数组的每个元素乘以b数组的对应元素,但只存储64位输出的低32位作为结果。

【讨论】:

如果这个命名看起来是倒退的(即纯 32x32 -> 32 位乘法不应该有简单的 mul 名称吗?)然后记住内在函数是为 SSE2 命名的 pmuldq / @ 987654330@,几年后 SSE4.1 pmulld 给了我们mullo__m256i 版本当然是同时引入的,与 AVX2 一起。

以上是关于矢量化:乘 _m256i 元素的主要内容,如果未能解决你的问题,请参考以下文章

从 __m256 中选择元素子集?

将打包的半字节组合成打包的字节

将向量的特定元素广播到另一个向量

如何检查 256i(16 位)向量以了解它是不是包含任何大于零的元素?

基于布尔掩码将元素移动到 SIMD 寄存器的左侧

如何以矢量化方式平均矩阵中的每个第 n 个元素?