Clang向量扩展与C++中的等式算子
Clang vector extensions and the equality operator in C++
我使用Clang SIMD矢量扩展编写了一个矢量类型。它工作得很好,除非我需要检查两个向量是否相等。对于Clang的向量类型,似乎没有正确定义==
运算符。奇怪的是,尝试将两个向量与==
进行比较似乎会得到与被比较的两个向量类型相同的第三个向量,而不是bool
。我觉得这很奇怪,因为应用其他操作(如+
或-
)可以顺利编译,并输出预期的结果。这是我的代码,用Clang 3.5(Xcode)编译:
// in vect.h
template <typename NumericType>
using vec2 = NumericType __attribute__((ext_vector_type(2))) ;
//in main.cpp
#include "vect.h"
int main(int argc, const char ** argv) {
vec2<int> v0 {0, 1} ;
vec2<int> v1 {0, 1} ;
vec2<int> sumVs = v0 + v1 ; //OK: evaluates to {0, 2} when run
bool equal = (v0 == v1) ; /* Compiler error with message: "Cannot initialize
a variable of type 'bool' with an rvalue of type 'int __attribute__((ext_vector_type(2)))'" */
return 0;
}
有没有任何方法可以将operator ==
与Clang的向量类型一起使用,或者有任何其他解决此问题的方法?由于它们被认为是原始的,而不是类类型,所以我不能自己重载比较运算符,并且编写全局equals()
函数显得笨拙和不雅。
更新:或者,如果没有人有我想要的解决方案,也许有人可以解释==
运算符在比较两个SIMD向量时的默认行为?
更新#2:Hurkyl建议==
对两个向量进行矢量化比较。我更新了我的代码来测试这种可能性:
template <typename NumericType>
using vec3 = NumericType __attribute__((ext_vector_type(3))) ;
int main(int argc, const char ** argv) {
vec3<int> v0 {1, 2, 3} ;
vec3<int> v1 {3, 2, 1} ;
auto compareVs = (v0 == v1) ;
return 0;
}
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) ...
那么我会接受的。但我希望有人能提出一些不那么笨拙的建议。
如果不使用编译器特定的语言扩展,而是使用instrinsic(例如xmmintrin.h
中提供的),则可以使用CCD_ 21及其亲缘关系。例如
__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));
此代码的工作原理如下。首先, 我不知道编译器支持的语言扩展,但如果你能获得底层的_mm_cmpeq_ps(a,b)
生成另一个__m128
,其中四个元素中的每一个都是所有位0或所有位1——我假设编译器生成的向量扩展的operator==
正是调用这个内在的)。接下来,int _mm_movemask_ps(__m128)
返回一个整数,其中第k个位设置为其参数的第k__m128
(用于128位宽的向量),那么你就可以使用这种方法(可能只调用_mm_movemask_ps()
)。
使用false的逐位补码作为真值并不罕见(例如,请参见BASIC)。
如果你想用它来实现一个无分支的三元运算符,它在矢量算术中特别有用:
r = (a == c)? b: d
成为
selector = (a == c)
r = (b & selector) | (d & ~selector)
- 写入向量<向量<bool>>
- 函数向量_指针有不同的原型,我可以构建一个吗
- std::向量与传递值的动态数组
- 将值指定给向量(2D)的向量中的某个位置
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 如何使用向量的template_back函数
- 尝试通过多个向量访问变量时,向量下标超出范围
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 如何在macOS中的旧扩展clang和gcc编译器中初始化数组和向量
- 如何将参数包扩展为向量<any>
- AVX2 根据条件将连续元素扩展到稀疏向量?(如AVX512 VP扩展)
- 我如何允许向量传递到info(),capture(),warn()等,同时避免非法扩展std名称空间
- 将RCPP函数扩展到任何类型的输入向量
- 堆栈分配的向量如何在 C++ 中扩展
- Clang向量扩展与C++中的等式算子
- 我应该使用SIMD还是向量扩展或其他什么
- 当无限扩展deque而不是向量时崩溃
- 在unique_ptrs向量中搜索时出现非标准扩展警告
- 我可以返回一个向量来用C++11扩展现有的向量吗
- 扩展向量迭代器以访问所包含类/结构的数据成员