3

我有一个关于 AVX_mm256_blend_pd功能的问题。

我想优化我大量使用该_mm256_blendv_pd功能的代码。不幸的是,这具有相当高的延迟和低吞吐量。此函数将三个__m256d变量作为输入,其中最后一个变量表示用于从前 2 个变量中进行选择的掩码。

我发现了另一个函数 ( _mm256_blend_pd),它采用位掩码而不是__m256d变量作为掩码。当掩码是静态的时,我可以简单地传递一些东西,比如 0b0111从第一个变量中获取第一个元素和第二个变量的最后 3 个元素。_mm_cmp_pd但是在我的情况下,掩码是使用返回__m256d变量的函数计算的。我发现我可以用来_mm256_movemask_pd从掩码返回一个 int,但是当将它传递给函数时,_mm256_blend_pd我得到一个错误error: the last argument must be a 4-bit immediate

有没有办法使用它的前 4 位传递这个整数?或者是否有另一个类似于 movemask 的功能可以让我使用_mm256_blend_pd?或者我可以使用另一种方法来避免使用对这个用例更有效的 cmp、movemask 和 blend 吗?

4

1 回答 1

5

_mm256_blend_pdvblendpd将其控制操作数作为立即常数嵌入到指令的机器代码中的内在函数。(这就是汇编/机器代码术语中“立即”的含义。)

在 C++ 术语中,控制 arg 必须是constexpr这样,编译器才能在编译时将其嵌入到指令中。您不能将它用于运行时变量混合。

不幸的是,像可变混合指令这样vblendvpd的速度较慢,但​​它们在 Skylake 上“仅”2 微秒,具有 1 或 2 个周期延迟(取决于您测量关键路径通过的输入)。( uops.info )。在 Skylake 上,这些微指令可以在 3 个矢量 ALU 端口中的任何一个上运行。(不过,在 Haswell/Broadwell 上更糟糕,仅限于端口 5,通过随机播放来争夺它)。Zen 甚至可以将它们作为单个 uop 运行。

在 AVX512 使屏蔽成为您可以作为其他指令的一部分执行的一流操作并为我们提供单 uop 混合指令(如vblendmpd ymm0{k1}, ymm1, ymm2(根据屏蔽寄存器混合))之前,一般情况下没有什么比这更好的了。

在某些特殊情况下,您可以有用地_mm256_and_pd有条件地归零而不是混合,例如,在 an 之前将输入归零add而不是在之后进行混合。


TL:DR:允许您在控件编译时常量_mm256_blend_pd的特殊情况下使用更快的指令。

于 2020-05-21T02:19:24.890 回答