如何为__m256值中的所有位设置值1? 使用AVX或AVX2内在函数?
要获取全部零,您可以使用_mm256_setzero_si256()
。
要获得所有这些,我目前正在使用_mm256_set1_epi64x(-1)
,但我怀疑这比全零情况要慢。这里是否涉及内存访问或Salar / SSE / AVX切换?
我似乎无法在AVX中找到一个简单的按位NOT操作? 如果可以,我可以简单地使用setzero,然后使用向量NOT。
答案 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); }
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
),但它比任何可能的双指令序列更好,并且通常比负载更好。另请参阅x86标记wiki。
编译器不喜欢generate more complex constants on the fly,即使是那些可以通过简单移位从全部生成的编译器。即使您尝试编写__m128i float_signbit_mask = _mm_srli_epi32(_mm_set1_epi16(-1), 1)
,编译器通常会进行常量传播并将向量放入内存中。这使得它们可以在以后使用时将它折叠到内存操作数中,如果没有循环来提升常量。
我似乎无法在AVX中找到一个简单的按位NOT操作?
你通过与所有人进行异或来做到这一点。