在 intel intrinsics (AVX) 中使用混合指令
Using the blend instructions in intel intrinsics (AVX)
我对 AVX _mm256_blend_pd
函数有疑问。
我想优化我大量使用 _mm256_blendv_pd
函数的代码。不幸的是,这具有相当高的延迟和低吞吐量。此函数将三个 __m256d
变量作为输入,其中最后一个表示用于 select 来自前 2 个变量的掩码。
我找到了另一个函数 (_mm256_blend_pd
),它采用位掩码而不是 __m256d
变量作为掩码。当掩码是静态的时,我可以简单地传递类似 0b0111
的东西来从第一个变量中获取第一个元素和第二个变量的最后 3 个元素。然而,在我的例子中,掩码是使用 _mm_cmp_pd
函数计算的,其中 return 是一个 __m256d
变量。我发现我可以使用掩码中的 _mm256_movemask_pd
到 return 一个整数,但是当将它传递给函数 _mm256_blend_pd
时,我得到一个错误 error: the last argument must be a 4-bit immediate
.
有没有办法使用它的前 4 位来传递这个整数?或者是否有另一个类似于 movemask 的函数可以让我使用 _mm256_blend_pd
?或者我可以使用另一种方法来避免使用 cmp、movemask 和 blend 对这个用例更有效吗?
_mm256_blend_pd
是 vblendpd
的内在函数,它将其控制操作数作为立即数,嵌入到指令的机器代码中。 (这就是 "immediate" 在汇编/机器代码术语中的意思。)
在 C++ 术语中,控制参数必须是 constexpr
以便编译器可以在编译时将其嵌入到指令中。您不能将其用于 运行 时变混合。
不幸的是,像 vblendvpd
这样的可变混合指令速度较慢,但它们在 Skylake 上是 "only" 2 微指令,具有 1 或 2 个周期的延迟(取决于您正在测量的输入通过的关键路径)。 (uops.info)。在 Skylake 上,这些 uops 可以在 3 个向量 ALU 端口中的任何一个上 运行。 (不过,在 Haswell/Broadwell 上更糟,仅限于端口 5,与洗牌竞争)。 Zen 甚至可以 运行 它们作为一个 uop。
在 AVX512 将屏蔽作为您可以作为其他指令的一部分执行的第一个 class 操作之前,没有什么比一般情况更好的了,并为我们提供单 uop 混合指令,如 vblendmpd ymm0{k1}, ymm1, ymm2
(混合根据屏蔽寄存器)。
在某些特殊情况下,您可以有用地 _mm256_and_pd
有条件地置零而不是混合,例如在 add
之前将输入归零,而不是在之后混合。
TL:DR: _mm256_blend_pd
允许您在控制 是 编译时常量的特殊情况下使用更快的指令。
我对 AVX _mm256_blend_pd
函数有疑问。
我想优化我大量使用 _mm256_blendv_pd
函数的代码。不幸的是,这具有相当高的延迟和低吞吐量。此函数将三个 __m256d
变量作为输入,其中最后一个表示用于 select 来自前 2 个变量的掩码。
我找到了另一个函数 (_mm256_blend_pd
),它采用位掩码而不是 __m256d
变量作为掩码。当掩码是静态的时,我可以简单地传递类似 0b0111
的东西来从第一个变量中获取第一个元素和第二个变量的最后 3 个元素。然而,在我的例子中,掩码是使用 _mm_cmp_pd
函数计算的,其中 return 是一个 __m256d
变量。我发现我可以使用掩码中的 _mm256_movemask_pd
到 return 一个整数,但是当将它传递给函数 _mm256_blend_pd
时,我得到一个错误 error: the last argument must be a 4-bit immediate
.
有没有办法使用它的前 4 位来传递这个整数?或者是否有另一个类似于 movemask 的函数可以让我使用 _mm256_blend_pd
?或者我可以使用另一种方法来避免使用 cmp、movemask 和 blend 对这个用例更有效吗?
_mm256_blend_pd
是 vblendpd
的内在函数,它将其控制操作数作为立即数,嵌入到指令的机器代码中。 (这就是 "immediate" 在汇编/机器代码术语中的意思。)
在 C++ 术语中,控制参数必须是 constexpr
以便编译器可以在编译时将其嵌入到指令中。您不能将其用于 运行 时变混合。
不幸的是,像 vblendvpd
这样的可变混合指令速度较慢,但它们在 Skylake 上是 "only" 2 微指令,具有 1 或 2 个周期的延迟(取决于您正在测量的输入通过的关键路径)。 (uops.info)。在 Skylake 上,这些 uops 可以在 3 个向量 ALU 端口中的任何一个上 运行。 (不过,在 Haswell/Broadwell 上更糟,仅限于端口 5,与洗牌竞争)。 Zen 甚至可以 运行 它们作为一个 uop。
在 AVX512 将屏蔽作为您可以作为其他指令的一部分执行的第一个 class 操作之前,没有什么比一般情况更好的了,并为我们提供单 uop 混合指令,如 vblendmpd ymm0{k1}, ymm1, ymm2
(混合根据屏蔽寄存器)。
在某些特殊情况下,您可以有用地 _mm256_and_pd
有条件地置零而不是混合,例如在 add
之前将输入归零,而不是在之后混合。
TL:DR: _mm256_blend_pd
允许您在控制 是 编译时常量的特殊情况下使用更快的指令。