Search 自定义二进制谓词并行化
我正在实现一个自定义的二进制谓词,由Search 自定义二进制谓词并行化,search,parallel-processing,thrust,Search,Parallel Processing,Thrust,我正在实现一个自定义的二进制谓词,由推力::max_元素搜索算法使用。它还跟踪一个单独的算法无法产生的感兴趣的值。它看起来像这样: struct cmp_class{ cmp_class(int *val1){ this->val1 = val1; } bool operator()(int i, int j){ if (j < *val1) { *val1 = j; } return i < j;
推力::max_元素搜索算法使用。它还跟踪一个单独的算法无法产生的感兴趣的值。它看起来像这样:
struct cmp_class{
cmp_class(int *val1){
this->val1 = val1;
}
bool operator()(int i, int j){
if (j < *val1) { *val1 = j; }
return i < j;
}
int *val1;
};
int val1 = ARRAY[0];
std::max_element(ARRAY, ARRAY+length, cmp(&val1));
.... use val1
struct cmp\u类{
cmp_类(int*val1){
这->val1=val1;
}
布尔运算符()(int i,int j){
如果(j<*val1){*val1=j;}
返回i
我的实际二进制谓词要复杂得多,但上面的示例抓住了它的要点:我将一个指向整数的指针传递给二进制谓词cmp
,然后它写入该整数以跟踪某个值(这里是最小值)。由于max\u元素
首先调用cmp()(数组[0],数组[1])
,然后调用cmp()(运行最大值,数组[i])
,因此我只查看cmp
中的值j
,因此初始化val1=ARRAY[0]
,以确保考虑数组[0]
如果我在主机上执行上述操作,例如使用std::max_元素
,则效果很好。val1
的值是给定已知数据时我所期望的值。但是,使用推力在GPU上执行此操作时,其值为off。我怀疑这是由于推力::max_元素
的并行化,它递归地应用于子数组,其结果形成另一个运行推力::max_元素
的数组,等等。这是否成立?一般来说,用于推力减小的二进制谓词预期是可交换的。我在这里使用“交换性”是指无论参数的呈现顺序如何,谓词结果都应该是有效的
在推力平行归约的初始阶段,参数可能会按照您可能期望的顺序呈现(即,按照传递给归约函数的向量的顺序,或者按照值在单个向量中出现的顺序)。但是,在平行归约过程的后期,参数的来源可能会混淆,在平行清扫期间。任何假定参数排序的二元比较函子都可能因推力平行约化而中断
在您的例子中,比较函子的布尔结果应该是有效的,无论给出的参数的顺序如何,在这方面,它似乎是正确的可交换的
但是,关于围绕val1内置的自定义存储功能,很明显,val1
中的结果可能会有所不同,这取决于参数传递给函子的顺序。在传递给函子的集合值(i,j)中假设这个简单的最大查找序列(假设Val1在大的值开始):< /p>
现在假设我们简单地颠倒参数呈现给函子的顺序:
values: 10 5 3 7 12
comparison pairs: (5,10) (3,10) (7,10) (12,10)
comparison result: 10 10 10 12
val1 storage: 10 10 10 10
另一个问题是,我可以看到,val1
上没有原子保护:
if (j < *val1) { *val1 = j; }
if(j<*val1){*val1=j;}
上述代码行在串行实现中可能是正常的。在并行多线程算法中,多个线程有可能同时访问(读写)*val1
,这将产生未定义的结果。因此,对于此类问题(“此代码为什么不工作?”),您需要提供一个。一般来说,用于推力减小的二进制谓词应该是可交换的-它们应该给出有效的结果,而不管参数传递给它们的顺序如何(即i
和j
)。您的函子(布尔)结果是可交换的,但函子在val1
中存储的内容的行为将根据参数的顺序而有所不同。我认为这可能是一个问题。
if (j < *val1) { *val1 = j; }