C++ C++;

C++ C++;,c++,clang,simd,C++,Clang,Simd,我使用Clang SIMD向量扩展编写了一个向量类型。它工作得很好,除非我需要检查两个向量是否相等。对于Clang的向量类型,似乎没有正确定义=运算符。尝试将两个向量与==进行比较,奇怪的是,它的计算结果似乎是与所比较的两个向量类型相同的第三个向量,而不是bool。我觉得这很奇怪,因为应用诸如+或-之类的其他操作可以顺利编译,并输出预期的结果。以下是我的代码,使用Clang3.5(Xcode)编译: LLDB将compareVs的值报告为{0,-1,0},如果发生这种情况,这看起来几乎是正确的,

我使用Clang SIMD向量扩展编写了一个向量类型。它工作得很好,除非我需要检查两个向量是否相等。对于Clang的向量类型,似乎没有正确定义
=
运算符。尝试将两个向量与
==
进行比较,奇怪的是,它的计算结果似乎是与所比较的两个向量类型相同的第三个向量,而不是
bool
。我觉得这很奇怪,因为应用诸如
+
-
之类的其他操作可以顺利编译,并输出预期的结果。以下是我的代码,使用Clang3.5(Xcode)编译:

LLDB将
compareVs
的值报告为{0,-1,0},如果发生这种情况,这看起来几乎是正确的,但是
true
将是-1,而
false
将是0,这似乎很奇怪

更新#3:好的,多亏了我得到的反馈,我现在对关系运算符和比较运算符如何应用于向量有了更好的理解。但我的基本问题仍然是一样的。我需要一种简单而优雅的方法来检查任意两个SIMD类型向量
v1
v2
,它们是否等效。换句话说,我需要能够检查
v1
v2
中的每个索引
I
v1[I]==v2[I]
,表示为单个布尔值(即,不是
bool
的向量/数组)。如果唯一的答案是一个函数,如:

template <typename NumericType>
bool equals(vec2<NumericType> v1, vec2<NumericType> v2) ...
模板
布尔等于(vec2v1,vec2v2)。。。

。。。那我就接受了。但我希望有人能提出一些不那么笨拙的建议。

使用false的位补码作为真值并不罕见(例如,请参见BASIC)

如果要使用它实现无分支三值运算符,则它在向量算术中特别有用:

r = (a == c)? b: d
变成

selector = (a == c)
r = (b & selector) | (d & ~selector)

如果不使用特定于编译器的语言扩展,而是使用instrinsic(如
xmmintrin.h
中提供的),则可以使用
\u mm\u movemask\u ps(\uu m128)
及其相关项。比如说

__m128 a,b;
/* some code to fill a,b with integer elements */
bool a_equals_b = 15 == _mm_movemask_ps(_mm_cmpeq_epi32(a,b));
这段代码的工作原理如下。首先,
\u mm\u cmpeq\u ps(a,b)
生成另一个
\u m128
,四个元素中的每一个都是所有位0或所有位1–我假定编译器生成的向量扩展调用的
运算符==
。接下来,
int\u mm\u movemask\u ps(\uu m128)
返回一个整数,其中第k位设置为其参数第k个元素的符号位。因此,如果所有元素的
a==b
,则
返回
1 | 2 | 4 | 8=15


我不知道编译器支持的语言扩展,但是如果您可以获得底层的
\uum128
(对于128位宽的向量),那么您可以使用这种方法(可能只有调用
\u mm\u movemask\u ps()
)。

如果我不得不猜测,
操作符==
正在进行向量化比较,从而返回一个结果向量,这很有意义。为了验证这个假设,我稍微修改了我的代码,我将用结果更新我的问题。或者直接在C/C++中,当您将
int
强制转换为
bool
时,对于
0
将得到
false
,对于其他任何内容将得到
true
,因此您在第二次更新中得到的结果非常好。
selector = (a == c)
r = (b & selector) | (d & ~selector)
__m128 a,b;
/* some code to fill a,b with integer elements */
bool a_equals_b = 15 == _mm_movemask_ps(_mm_cmpeq_epi32(a,b));