比较<=
的两个4x 64位整数AVX向量的最有效方法是什么。
来自英特尔内在指南我们
_mm256_cmpgt_epi64(__m256i a, __m256i b)
= a&gt; B'/ LI>
_mm256_cmpeq_epi64(__m256i a, __m256i b)
= a == b 进行比较
和
_mm256_and_si256(__m256i a, __m256i b)
= a&amp; B'/ LI>
_mm256_andnot_si256(__m256i a, __m256i b)
=〜&amp; B'/ LI>
_mm256_or_si256(__m256i a, __m256i b)
= a | B'/ LI>
_mm256_xor_si256(__m256i a, __m256i b)
= a ^ b 用于逻辑操作。
我的方法是:
// check = ( a <= b ) = ~(a > b) & 0xF..F
__m256i a = ...
__m256i b = ...
__m256i tmp = _mm256_cmpgt_epi64(a, b)
__m256i check = _mm256_andnot_si256(tmp, _mm256_set1_epi64x(-1))
答案 0 :(得分:3)
你是对的,没有直接的方法来获得你真正想要的面具,只有一个倒置的面具:A gt B
= A nle B
。
没有vector-NOT指令,所以你需要一个all-1向量以及一个反向向量的额外指令。 (或者是一个全零和_mm256_cmpeq_epi8
的向量,但是它不能在_mm256_xor_si256
上使用全向量的多个执行端口上运行。)请参阅x86标记维基性能信息,尤其是Agner Fog的指南。
另一个按位布尔选项_mm256_andn_si256
和xor一样好。这不是可交换的,而且在心理上验证你是否正确是稍微复杂一点。 xor-with-all-ones是翻转所有位的好习惯。
在大多数代码中,不是花费反转掩码的指令,而是以相反的方式使用它。
e.g。如果它是blendv
的输入,则将操作数的顺序反转为混合。而不是
_mm256_blendv_epi8(a, b, A_le_B_mask)
,请使用
_mm256_blendv_epi8(b, a, A_nle_B_mask)
如果您要使用面具_mm_and
,请改用_mm_andn
。
如果你要去_mm_movemask
并测试全零,你可以改为测试全部。它将编译为cmp eax, -1
指令而不是test eax,eax
,这同样有效。如果您要对第一个进行比特扫描,则必须将其反转。整数not
指令(在movemask结果上使用~
)比在向量上执行要便宜。
如果您要进行OR或XOR,那么您只会遇到问题,因为这些指令不具有否定其输入的风格。 (IDK,如果英特尔只是不想添加PORN
助记符,但可能PAND
和PANDN
更多地使用,尤其是在变量混合指令之前。