将__m256值设置为所有一位

时间:2016-05-26 19:58:49

标签: bit-manipulation intrinsics avx avx2

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

要获取全部零,您可以使用_mm256_setzero_si256()

要获得所有这些,我目前正在使用_mm256_set1_epi64x(-1),但我怀疑这比全零情况要慢。这里是否涉及内存访问或Salar / SSE / AVX切换?

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

1 个答案:

答案 0 :(得分:7)

另请参阅Set all bits in CPU register to 1 efficiently,其中包括AVX,AVX2和AVX512 zmm和k(掩码)寄存器。

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

#include <immintrin.h>
__m256i all_ones(void) { return _mm256_set1_epi64x(-1); }

compiles to

    vpcmpeqd        ymm0, ymm0, ymm0
    ret

使用gcc6.1和clang3.8。

支持avx2的gcc的第一个版本已经足够了解这个优化。使用-mavx -mno-avx2,gcc从内存中加载一个全向的向量。 Clang使用了128比特的全部并使用vinsertf128

正如Agner Fog's optimizing assembly guide的向量部分所描述的那样,以这种方式生成常量很便宜。它仍然需要向量执行单元来生成全1(unlike _mm_setzero),但它比任何可能的双指令序列更好,并且通常比负载更好。另请参阅标记wiki。

编译器不喜欢generate more complex constants on the fly,即使是那些可以通过简单移位从全部生成的编译器。即使您尝试编写__m128i float_signbit_mask = _mm_srli_epi32(_mm_set1_epi16(-1), 1),编译器通常会进行常量传播并将向量放入内存中。这使得它们可以在以后使用时将它折叠到内存操作数中,如果没有循环来提升常量。

  

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

你通过与所有人进行异或来做到这一点。