并行化std :: nth_element和std :: partition

时间:2013-08-29 16:00:39

标签: c++ algorithm sorting parallel-processing opencl

我正在移植使用std::nth_elementstd::partition到OpenCL的C ++代码。

nth_element是一个selection algorithm,它将第n个最小数字放在第n个点的数组中,并排列其余元素,以便所有小于此数字的元素都在数组之前,以及比它更大的所有元素。实际上,nth_element将数组排序为3个桶:数字本身,所有小于它的数字,以及所有大于它的数字。

通常,使用递归分区实现nth_element:选择一个元素,根据元素是否小于此元素对元素进行分区。然后,选择包含数组第n个元素的存储桶并递归该存储桶。 nth_element和完全快速排序之间的主要区别在于快速排序在两个桶上进行递归,而不仅仅是包含第n个元素的桶。


partitionnth_element的较弱版本,它只将数组分为2个桶:条件为true的那些,以及为false的那些桶。我链接的网站提供了实施:

while (first!=last) {
    while (pred(*first)) {
        ++first;
        if (first==last) return first;
    }
    do {
        --last;
        if (first==last) return first;
    } while (!pred(*last));
    swap (*first,*last);
    ++first;
}
return first;

其中pred是一个函数,用于评估元素是否应该在第一个存储桶中。基本上,这个函数迭代地找到数组中最外面的一对元素,这些元素位于错误的位置,然后交换它们,当元素对是相同的元素时停止。


以下是关于并行nth_elementpartition的初步想法:

可以使用原子比较和交换来实现分区,但我不确定如何覆盖可以交换的所有可能的值对。没有明显的方法可以在多个线程之间划分工作,因为分区需要比较可能彼此相邻的元素或者在数组的相对两端。我也没有办法避免让线程B与已经被线程A交换的元素进行比较,这是低效的。

nth_element似乎更不可并行化,因为它是递归的:每个分区都依赖于前一个分区已经部分排序的元素。

据推测,对于这两种功能而言,有效的并行化策略需要与典型的串行代码完全不同的方法。


nth_elementpartition的高效并行实施是否已经存在?如果没有,什么是良好的并行化策略?

1 个答案:

答案 0 :(得分:2)

Cuda THRUST已实施分区功能(http://docs.nvidia.com/cuda/thrust/index.html#reordering)。

主要思想应该是: 使用前缀和来计算数组中元素的位置,然后重新排列数组。