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