哪些指令用于比较由4 * 32位浮点值组成的两个128位向量?
是否有指令认为双方的NaN值相等?如果不是,提供反身性的变通方(即NaN等于NaN)对性能的影响有多大?
我听说,与IEEE语义相比,确保反身性会产生显着的性能影响,因为NaN并不等于自己,而且我想知道这种影响是否会很大。
我知道您在处理浮点值时通常需要使用epsilon比较而不是精确的质量。但是这个问题是关于完全相等的比较,你可以用它来消除哈希集中的重复值。
要求
+0
和-0
必须相等。NaN
必须与自己相等。true
,如果至少有一个元素不同,则为false。其中true
由标量整数1
表示,false
由0
表示。测试用例
(NaN, 0, 0, 0) == (NaN, 0, 0, 0) // for all representations of NaN
(-0, 0, 0, 0) == (+0, 0, 0, 0) // equal despite different bitwise representations
(1, 0, 0, 0) == (1, 0, 0, 0)
(0, 0, 0, 0) != (1, 0, 0, 0) // at least one different element => not equal
(1, 0, 0, 0) != (0, 0, 0, 0)
我实现此想法的想法
我认为可以使用NotLessThan
组合两个CMPNLTPS
比较(and
?)来获得所需的结果。汇编程序等效于AllTrue(!(x < y) and !(y < x))
或AllFalse((x < y) or (y > x)
。
背景
这个问题的背景是微软计划向.NET添加Vector类型。我正在争论一种反身.Equals
方法,并且需要更清楚地了解这种反身性能对IEEE平等的性能影响有多大。有关长篇故事,请参阅programmers.se上的Should Vector<float>.Equals
be reflexive or should it follow IEEE 754 semantics?。
答案 0 :(得分:3)
这是一种可能的解决方案 - 但效率不高,需要6条指令:
__m128 v0, v1; // float vectors
__m128 v0nan = _mm_cmpeq_ps(v0, v0); // test v0 for NaNs
__m128 v1nan = _mm_cmpeq_ps(v1, v1); // test v1 for NaNs
__m128 vnan = _mm_or_si128(v0nan, v1nan); // combine
__m128 vcmp = _mm_cmpneq_ps(v0, v1); // compare floats
vcmp = _mm_and_si128(vcmp, vnan); // combine NaN test
bool cmp = _mm_testz_si128(vcmp, vcmp); // return true if all equal
请注意,上面的所有逻辑都是反转的,这可能会使代码难以理解(OR
s实际上是AND
s,而反之亦然)。