有没有人有使用TBB有效并行化std :: partition的技巧?这已经完成了吗?
以下是我的想法:
*我希望在平均情况下,这个区域与数组的长度相比会很小,或者与在连续块中对数组进行分区时所需的交换进行比较。
在我尝试之前有任何想法吗?
答案 0 :(得分:3)
我将其视为并行样本排序的退化案例。 (可以找到样本排序的并行代码here。)设N是项目数。简并样本排序将需要Θ(N)临时空间,具有Θ(N)工作和Θ(P + lg N)跨度(关键路径)。最后两个值对分析很重要,因为加速仅限于工作/跨度。
我假设输入是随机访问序列。步骤是:
有一种方法可以将步骤4的扫描嵌入到步骤3和5中,这样可以将跨度减小到Θ(lg N),但我怀疑它是否值得增加复杂性。
如果使用tbb :: parallel_for循环来并行化步骤3和5,请考虑使用affinity_partitioner来帮助步骤5中的线程从步骤3中获取它们在缓存中留下的内容。
请注意,对于Θ(N)内存加载和存储,分区仅需要Θ(N)工作。内存带宽很容易成为加速的限制资源。
答案 1 :(得分:2)
为什么不与std::partition_copy
类似的东西并行?原因是:
std::partition
,就像Adam的解决方案中的就地交换需要对数复杂性,因为结果的递归合并。应用parallel_for
(对于随机访问迭代器)或tbb::parallel_for_each
(对于非随机访问迭代器)来开始处理输入范围非常简单。每个任务都可以独立存储'true'和'false'结果。有很多方法可以存储结果,有些方法来自我的头脑:
tbb::parallel_reduce
(仅用于随机访问迭代器),将结果本地存储到任务主体,并将其从join()
移动附加到其他任务tbb::concurrent_vector
的方法grow_by()
复制本地结果,或者在到达时单独复制push()
每个结果。tbb::combinable
TLS容器中缓存线程局部结果并稍后将它们组合 std::partition_copy
的确切语义可以通过从上面临时存储中复制来实现,或者
atomic<size_t>
游标来同步存储结果的位置(假设有足够的空间)答案 2 :(得分:0)
您的方法应该是正确的,但为什么不遵循常规的分而治之(或parallel_for)方法?对于两个线程:
这应该更好地利用缓存。
答案 3 :(得分:0)
在我看来,在我尝试之前,这应该很好地并行化,任何想法?
嗯......也许是几个:
std::partition
的复杂性是线性的,因此很容易高估任务的速度。既然你问过并给出了一个算法,我希望你真的需要在这里进行并行化。如果是这样 - 没有什么可以补充的,算法本身看起来很好:)