推力自定义二进制谓词并行化

时间:2014-12-22 08:15:57

标签: search parallel-processing thrust

我正在实现thrust::max_element搜索算法使用的自定义二进制谓词。它还跟踪算法本身无法产生的感兴趣的值。它看起来像这样:

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

我的实际二元谓词相当复杂,但上面的例子捕获了它的要点:我将指向整数的指针传递给二进制谓词cmp,然后写入该整数以保持追踪某些价值(这里是最低限度)。由于max_element首先调用cmp()(ARRAY[0],ARRAY[1])然后调用cmp()(running maximum,ARRAY[i]),我只会查看j内的值cmp,因此会初始化val1 = ARRAY[0]以确保{{1}考虑到了。

如果我在主机上执行上述操作,例如使用ARRAY[0],则可以正常工作。鉴于已知数据,std::max_element的值是我所期望的。但是,使用Thrust在GPU上执行此操作,其值已关闭。我怀疑这是由于val1的并行化,它是在子数组上递归应用的,其结果形成另一个运行thrust::max_element的数组,等等。这有用吗?

1 个答案:

答案 0 :(得分:2)

通常,用于推力减少的二元谓词预计是可交换的。我在这里使用“可交换”意味着谓词结果应该是有效的,无论参数的显示顺序如何。

在推力平行减少的初始阶段,参数很可能以您可能预期的顺序呈现(即按照传递给reduce函数的向量的顺序,或者按照值出现在单个向量。)然而,在并行缩减过程的后期,在并行扫描期间,参数的起源可能会混淆。假定对参数进行排序的任何二元比较函子都可能被破坏,以推进并行减少。

在您的情况下,无论所呈现的参数顺序如何,比较仿函数的布尔结果都应该是有效的,并且在这方面它似乎是正确的可交换的。

但是,关于val1内置的自定义存储功能,val1中的结果可能会有所不同,具体取决于参数传递给仿函数的顺序。在传递给函子的设定值中考虑这​​个简单的最大查找序列为(i,j)(假设val1以较大的值开始):

values:            10      5      3      7      12
comparison pairs:      (10,5) (10,3) (10,7) (10,12) 
comparison result:        10     10     10      12
val1 storage:              5      3      3       3

现在假设我们只是颠倒了参数呈现给仿函数的顺序:

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

上述代码行在串行实现中可能没问题。在并行多线程算法中,您可以同时访问多个线程(同时读取写入)*val1,这将导致未定义的结果。