AVX2 _mm256_cmp_pd返回数字值

AVX2 _mm256_cmp_pd to return number values

提问人:Vladislav Kogan 提问时间:11/15/2022 最后编辑:Peter CordesVladislav Kogan 更新时间:11/15/2022 访问量:533

问:

我的目标是将比较矢量化,以便将来将它们用作掩码。

问题是 _mm256_cmp_pd 返回 NaN 而不是 1.0。在 AVX2 中进行比较的正确方法是什么?

AVX2 代码:

__m256d _numberToCompare = _mm256_set1_pd(1.0);
__m256d _compareConditions = _mm256_set_pd(0.0, 1.0, 2.0, 3.0);

__m256d _result = _mm256_cmp_pd(_numberToCompare, _compareConditions, _CMP_LT_OQ); //a < b ordered (non-signalling) 
alignas(8) double res[4];
_mm256_store_pd(&res[0], _result);
for (auto i : res) {
    std::cout << i << '\t';
}
   
__m256d _result2 = _mm256_cmp_pd(_numberToCompare, _compareConditions, _CMP_LE_OQ); //a <= b ordered (non-signalling)   
alignas(8) double res2[4];
_mm256_store_pd(&res2[0], _result2);
for (auto i : res2) {
    std::cout << i << '\t';
}
std::cout << '\n';

GodBolt 链接

预期结果(我会在标量代码中得到的结果):

0 0 1 1
0 1 1 1

实际结果:

-nan    -nan    0       0
-nan    -nan    -nan    0
  1. 为什么比较的结果是NaN?
  2. 获得预期结果的正确方法是什么?
C++ x86 比较 AVX AVX2

评论

2赞 Peter Cordes 11/15/2022
SSE 比较的近似重复返回 NAN 的向量。有关使用比较结果的示例,请参阅是否可以使 C++ 生成 cmpps 指令而不进行内联汇编?英特尔内部函数:向量比较结果到显示 cmp 结果的整数操作的布尔转换数组。或者用于浮点等式比较的 SIMD 指令(使用 NaN == NaN)(在 asm 中,但 insns 存在内部函数。
2赞 Peter Cordes 11/15/2022
另一个很好的例子:我如何获得英特尔架构 SIMD __m128 的标志 - 问题想要一个值为 -1.0 / 0 / +1.0 的浮点数,这是一个 X-Y 问题。我的回答猜测他们想将另一个值乘以该值,但您可以直接使用按位运算更轻松地应用它。否定浮点数只是用 1 对符号位进行异或运算(即 xor 用-0.0)
0赞 Vladislav Kogan 11/18/2022
谢谢。但是,我不认为它是重复的。是的,SSE/AVX 都是 SIMD,但 AVX2 是不同的指令集扩展。AVX2 语法的答案会更清楚。我认为 AVX2 应该有一个单独的 Q-A 页面(并试图做到这一点)。
1赞 Peter Cordes 11/18/2022
是的,没有一个不是非常相似,无法作为副本关闭,但从 SSE4.1 () 到 AVX2 的概念是相同的。 HSP的 与理解按位掩码的概念以将元素归零或使用混合在两个值之间进行选择相比,这是一个微不足道的区别。是的,您自我回答的问答(如何在 AVX2 中执行掩码/条件/无分支算术运算)希望对未来的读者有所帮助,以证明这一点。blendvpd_mm_mm256

答:

3赞 chtz 11/15/2022 #1

广告 1:结果是一个位掩码(二进制表示 true 或 false),可以与按位运算符一起使用。0xffff'ffff'ffff'ffff0

广告 2:如果你真的想要,你可以计算(但通常,直接使用位掩码更有效)。_result = _mm256_and_pd(_result, _mm256_set1_pd(1.0))10

还要注意的是,参数是按“big-endian”顺序排列的,即地址最高的元素是第一个参数(不要问我为什么英特尔决定这样做)——如果你更喜欢 little-endian,你可以改用。_mm256_set_pd_mm256_setr_pd