在 AVX 内在函数 vec 中填充常量浮点数

Fill constant floats in AVX intrinsics vec

我正在使用 AVX 内在函数进行矢量化,我想将像 1.0 这样的常量浮点数填充到矢量 __m256 中。所以在一个寄存器中我得到了一个向量{1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0} 有谁知道怎么做吗?

类似这个问题constant float with SIMD

但我使用的是 AVX 而不是 SSE

AVX intrinsics load and store operations 见此处。您只需声明一个浮点数组、一个 AVX 向量 __m256,然后使用适当的操作将浮点数组加载为 AVX 向量。

在这种情况下,指令_mm256_load_ps就是你想要的。

更新:如评论中所述,数据必须32位对齐。有关详细说明,请参阅 Intel data alignment documentation。根据 Peter 的评论,我已经使解决方案代码更清晰。启用优化(-O3)后,这将生成与 Paul 的答案相同的代码(也启用了优化)。然而,在没有启用优化的情况下,指令的数量是相同的,但所有 8 个浮点数都被存储,而不是像 Paul 的答案那样只存储一个浮点数。

这里是修改后的例子:

#include <immintrin.h> // For AVX instructions

#ifdef __GNUC__
  #define ALIGN(x) x __attribute__((aligned(32)))
#elif defined(_MSC_VER)
  #define ALIGN(x) __declspec(align(32))
#endif

static constexpr ALIGN(float a[8]) = {1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f};

int main() {
  // Load the float array into an avx vector
  __m256 vect = _mm256_load_ps(a);
}

您可以使用 Godbolt interactive C++ compiler 使用一些编译器轻松检查汇编输出。

你可以在没有 const 数组的情况下使用它

pcmpeqw xmm0, xmm0
pslld   xmm0, 25
psrld   xmm0, 2

其他常量的制作方法参见Agner Fog的优化指南,13.10 Generating constants - Making floating point constants in XMM registers

pcmpeqw xmm0, xmm0 ; 1.5f
pslld   xmm0, 24
psrld   xmm0, 2

pcmpeqw xmm0, xmm0 ; -2.0f
pslld   xmm0, 30

另见

最简单的方法是使用_mm256_set1_ps:

__m256 v = _mm256_set1_ps(1.0f);