如何比较__m128类型?

时间:2011-05-18 09:18:37

标签: x86 sse simd

__m128 a;
__m128 b;

如何编码a != b

使用方法:_mm_cmpneq_ps_mm_cmpneq_ss

如何处理结果?

无法找到足够的文档。

3 个答案:

答案 0 :(得分:16)

您应该使用_mm_cmpneq_ps。然而,对比SIMD代码的解释与标量代码略有不同。您想测试任何相应的元素不相等吗?或所有对应的元素不相等?

要测试来自_mm_cmpneq_ps的4次比较的结果,您可以使用_mm_movemask_epi8

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

__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

对于文档,您需要来自英特尔的这两个卷:

Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2A: Instruction Set Reference, A-M

Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2B: Instruction Set Reference, N-Z

答案 1 :(得分:1)

这个问题的答案还取决于你是否想要实际的不平等,你在@PaulR所展示的内容中使用了什么:

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;
}

或者是否要使用某个epsilon来指定元素仍然被认为是"相等"如果他们的差异不超过阈值:

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;
}

示例:

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

答案 2 :(得分:-1)

考虑使用SSE4.1指令ptest

if(_mm_testc_si128(_mm_castps_si128(a), _mm_castps_si128(b))) {
   /* equal */
} else {
   /* not equal */
} 

This是一条指令。