X86 如何比较m128类型?

X86 如何比较m128类型?,x86,sse,simd,X86,Sse,Simd,如何编写a!=b 使用方法:\u-mm\u-cmpneq\u-ps或\u-mm\u-cmpneq\u-ss 如何处理结果 找不到足够的文档。您可能应该使用\u mm\u cmpneq\u ps。然而,SIMD代码与标量代码的比较解释略有不同。是否要测试任何不相等的对应元素?或者所有相应的元素都不相等 要测试来自\u mm\u cmpneq\u ps的4个比较结果,可以使用\u mm\u movemask\u epi8 请注意,比较浮点值是否相等或不相等通常不是一个好主意,除非是在非常特殊的情况下

如何编写
a!=b

使用方法:
\u-mm\u-cmpneq\u-ps
\u-mm\u-cmpneq\u-ss

如何处理结果


找不到足够的文档。

您可能应该使用
\u mm\u cmpneq\u ps
。然而,SIMD代码与标量代码的比较解释略有不同。是否要测试任何不相等的对应元素?或者所有相应的元素都不相等

要测试来自
\u mm\u cmpneq\u ps
的4个比较结果,可以使用
\u mm\u movemask\u epi8

请注意,比较浮点值是否相等或不相等通常不是一个好主意,除非是在非常特殊的情况下。

__m128 a;
__m128 b;
对于需要英特尔提供这两个卷的文档:




这个问题的答案还取决于你是否想要实际的不平等,你可以使用@PaulR所展示的东西:

__m128i vcmp = (__m128i)_mm_cmpneq_ps(a, b); // compare a, b for inequality
uint16_t test = _mm_movemask_epi8(vcmp); // extract results of comparison
if (test == 0xffff)
    // *all* elements not equal
else if (test != 0)
    // *some* elements not equal
else
    // no elements not equal, i.e. all elements equal
或者,如果元素之间的差异不超过阈值,是否要使用一些ε来指定元素仍然被视为“相等”:

bool fneq128_a (__m128 const& a, __m128 const& b)
{
    // returns true if at least one element in a is not equal to 
    // the corresponding element in b
    return _mm_movemask_ps(_mm_cmpeq_ps(a, b)) != 0xF;
}
例如:

bool fneq128_b (__m128 const& a, __m128 const& b, float epsilon = 1.e-8f)
{
    // epsilon vector
    auto eps = _mm_set1_ps(epsilon);
    // absolute of difference of a and b
    auto abd = _mm_andnot_ps(_mm_set1_ps(-0.0f), _mm_sub_ps(a, b));
    // compare abd to eps
    // returns true if one of the elements in abd is not less than 
    // epsilon
    return _mm_movemask_ps(_mm_cmplt_ps(abd, eps)) != 0xF;
}

彼得是对的!!!在前面的方法中,针对0.0f值的测试可能会失败

请考虑这个宏。 #定义相等(A,B)_mm_testz_si128(_mm_xor_si128(_mm_castps_si128(A),_mm_castps_si128(B)),
_mm_xor_si128(_mm_castps_si128(A),_mm_castps_si128(B)))


这将导致两条指令。

我希望您理解为什么比较浮点值的相等/不相等不是一个好主意?(这适用于标量代码和SIMD代码。)文件可从Intel和AMD获得。寻找处理器手册。@保罗R:SIMD代码不一定是浮点。@迪特里希:我知道,但它在这个特定的案例中。BTW,在VisualStudio中,常规C++的注册表不起作用,但仍然可以使用固有的MyMyCaspScript将其转换到Y12M128i。si128@Virgil:是的,这只是Visual Studio C/C++编译器和SSE代码的几个问题领域之一——还有一些令人讨厌的(似乎是任意的)ABI限制。我建议使用gcc或更好的Intel的ICC,并尽可能避免使用Windows在这里,您通常希望在32位整数的低位获得一个简单的4位掩码。这不是对相等性的测试,而是测试
~a&b==all zero
(跨越所有128位)。另请参见:使其成为宏不方便;您还可以将其设置为一个内联函数,以便可以使用临时函数来保存按位异或结果。但是,考虑到NaN==NaN(具有相同的负载)和
-0.0!=0.0
。而不是IEEE浮点相等规则。
auto a = _mm_set_ps(0.0, 0.0, 0.0, 0.0);
auto b = _mm_set_ps(0.0, 0.0, 0.0, 1.e-15);
std::cout << fneq128_a(a, b) << ' ' << fneq128_b(a, b) << "\n";
 1 0