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

Lbj*_*j_x 2 c c++ simd intrinsics avx

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

它类似于这个问题常量浮点数和SIMD

但我使用AVX而不是SSE

Rob*_*cas 5

请参阅此处了解AVX内在函数加载和存储操作.您只需要声明一个浮点数组,一个AVX向量__m256,然后使用适当的操作将float数组加载为AVX向量.

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

更新:如评论中所述,数据必须是32位对齐的.有关详细说明,请参阅英特尔数据对齐文档.根据彼得的评论,我已经使解决方案代码更加清晰.通过优化enabled(-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);
}
Run Code Online (Sandbox Code Playgroud)

您可以使用Godbolt交互式C++编译器通过一些编译器轻松检查汇编输出.

  • @Lbj_x:Paul R的答案更好:告诉编译器你真正想要的是什么,而不是如何去做.它将使用任何可用/适用的技巧(如广播指令).**你绝对不想强制它制作*local*数组,而不是从全局/静态常量加载.**实际上制作本地数组意味着存储到堆栈.还要注意,win32的gcc编译会阻塞这段代码,因为它不是Unix与Windows,它是GNU C(`__attribute__`)与MSVC(`__declspec`). (2认同)
  • 将我的投票改为upvote :)我把*this*代码放在godbolt上:https://goo.gl/qIXGlK.我还有其他一些方法.您的问题中的链接是关于godbolt的其他一些代码.gcc以不同的方式编译它们,但是clang甚至可以通过静态数组看到并使用`vbroadcastss`.对于在godbolt上测试代码,`main`是一个糟糕的选择:gcc将其标记为"冷"并且优化得更少.另外,编写函数来获取args和/或返回结果*比担心`main`优化为`return 0;`更容易*.记住,我们只想看看asm,而不是运行它. (2认同)

phu*_*clv 5

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

pcmpeqw xmm0, xmm0
pslld   xmm0, 25
psrld   xmm0, 2
Run Code Online (Sandbox Code Playgroud)

请参阅 Agner Fog 的优化指南中创建其他常量的方法,13.10 生成常量 - 在 XMM 寄存器中制作浮点常量

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

pcmpeqw xmm0, xmm0 ; -2.0f
pslld   xmm0, 30
Run Code Online (Sandbox Code Playgroud)

也可以看看


Pau*_*l R 5

最简单的方法是使用_mm256_set1_ps:

__m256 v = _mm256_set1_ps(1.0f);
Run Code Online (Sandbox Code Playgroud)

  • [here](http://stackoverflow.com/a/13222222/2542702)是我读到的内容。也许克朗现在已经解决了。 (2认同)