将__m256值设置为所有ONE位的最快方法

Bra*_*ram 2 bit-manipulation intrinsics avx avx2

如何为__m256值中的所有位设置值1?使用AVX或AVX2内在函数?

要获得全零,您可以使用_mm256_setzero_si256().

为了得到所有的,我正在使用_mm256_set1_epi64x(-1),但我怀疑这比全零情况慢.这里是否涉及内存访问或Salar/SSE/AVX切换?

我似乎无法在AVX中找到一个简单的按位NOT操作?如果可以,我可以简单地使用setzero,然后使用向量NOT.

Pet*_*des 7

另请参见将CPU寄存器中的所有位有效地设置为1,其中包括AVX,AVX2和AVX512 zmm和k(掩码)寄存器.


你显然甚至没有看到asm输出,这是微不足道的:

#include <immintrin.h>
__m256i all_ones(void) { return _mm256_set1_epi64x(-1); }
Run Code Online (Sandbox Code Playgroud)

编译成

    vpcmpeqd        ymm0, ymm0, ymm0
    ret
Run Code Online (Sandbox Code Playgroud)

用gcc6.1和clang3.8.


支持avx2的gcc的第一个版本已经足够了解这个优化.使用vcmptrueps dst, ymm0,ymm0,gcc从内存中加载一个全向的向量.Clang制作了128bit全能和使用-mavx -mno-avx2.


正如Agner Fog的优化装配指南的矢量部分所描述的那样,通过这种方式生成常数很便宜.它仍然需要一个向量执行单元来生成全1(不像vinsertf128),但它比任何可能的双指令序列都好,并且通常比负载更好.另请参阅标记wiki.

编译器不喜欢动态生成更复杂的常量,即使是那些可以通过简单移位从全部生成的常量生成的常量.即使您尝试通过编写_mm_setzero,编译器通常也会进行常量传播并将向量放入内存中.这使得它们可以在以后使用时将它折叠到内存操作数中,在这种情况下没有循环来提升常量.


我似乎无法在AVX中找到一个简单的按位NOT操作?

你通过XORing与所有人一起做到这一点.

  • @PeterCordes re:“编译器不喜欢即时生成更复杂的常量,即使是那些可以通过简单的转换从全一生成的常量”在 LLVM 中进行处理。它比人们想象的要复杂一点,但即将到来。 (2认同)