在我见过的合并排序的多线程版本中,多线程通常是在左右子数组的递归过程中完成的(即,每个线程都被分配了自己的子数组来处理),并且合并操作是由每个线程完成各自的工作后主线程。
我想知道是否有一种好方法可以对要合并 2 个已排序子数组的最终合并操作进行多线程处理?如果是这样,该怎么办?
实际上有一种方法可以将合并任务拆分到2个并发线程中:
我还没有在有关多线程归并排序的文献中看到过这种方法。我想知道它的性能是否比经典实现更好。
排序数组的合并可以分为 n 个独立的、可并行的任务。总体思路是从输入数据中选取值,并在自己的线程中合并这些值之间的子数组元素。步骤是:
这是一个具体的例子:
unsorted input: [a,w,d,y,u,p,l,s,c,e,g,h]
pick values: g and p
subarrays in last step of mergesort: a = [a,d,p,u,w,y] and b = [c,e,g,h,l,s]
indexes of picked values (or next highest) in a: a_ind=[2, 2]
indexes of picked values (or next highest) in b: b_ind=[2, 5]
add ends of array to indexes: a_ind=[0,2,2,6], b_ind=[0,2,5,6]
merge each of these in separate threads:
[a,d] with [c,e]
[] with [g, h, l]
[p,u,w,y] with [s]
这个例子效率很低,但根据我的经验,如果子数组很大并且你仔细选择n,它可以提供良好的并行化和更快的排序。
您可以在其他结果完成之前将单个线程的结果写入输出文件,因为您知道它从 a_ind[i] + b_ind[i] 开始,以及您在该线程上合并了多少个值。
一个挑战是找到一种平均分配工作的方法。我随机选择了值,并且选择了比我拥有的核心多得多的值,这对于在线程之间均匀分配工作非常有效。
这实际上只是 @chqrlie 答案的概括,但希望它可以帮助某人。