多线程合并排序->如何优化?

时间:2018-06-19 11:48:29

标签: c# multithreading

我尝试对合并排序算法进行多线程处理。该算法的简单形式是:(Merge()是标准合并算法)

static void MergeSort(this int[] array, int initial, int final) {
    if (initial == final) return;
    array.MergeSort(initial, (initial + final) / 2);
    array.MergeSort((initial + final) / 2 + 1, final);
    array.Merge(initial, final);
}

多线程版本是:

static void MergeSortMT(this int[] array, int initial, int final, int mtCount) {
    if (initial == final) return;

    if (mtCount > 0) {
        Task t = Task.Run(() =>
        {
            array.MergeSortMT(initial, (initial + final) / 2, mtCount - 1);
        });
        array.MergeSortMT((initial + final) / 2 + 1, final, mtCount - 1);

        t.Wait();
    }
    else
    {
        array.MergeSort(initial, (initial + final) / 2);
        array.MergeSort((initial + final) / 2 + 1, final);
    }
    array.Merge(initial, final);
}
此处的

mtCount指示线程分离将发生多少次。通常,整个排序由单个线程运行。如果mtCount为1,则总线程数变为2,如果mtCount为2,则总线程数变为4,依此类推。

以下是一些结果:

Method - Input Size - Times Run - Miliseconds

Merge 1000000 X 1000    606832
Merge 100000 X 1000     51061
Merge 10000 X 1000      4080
Merge 1000 X 1000       314
Merge 100 X 1000        22
Merge 10 X 1000         1

mtCount = 1
MergeMT 1000000 X 1000  258237
MergeMT 100000 X 1000   23498
MergeMT 10000 X 1000    2088
MergeMT 1000 X 1000     202
MergeMT 100 X 1000      57
MergeMT 10 X 1000       44

mtCount = 2
MergeMT 1000000 X 1000  188337
MergeMT 100000 X 1000   16836
MergeMT 10000 X 1000    1825
MergeMT 1000 X 1000     355
MergeMT 100 X 1000      162
MergeMT 10 X 1000       299

mtCount = 3
MergeMT 1000000 X 1000  175220
MergeMT 100000 X 1000   15276
MergeMT 10000 X 1000    1690
MergeMT 1000 X 1000     455
MergeMT 100 X 1000      296
MergeMT 10 X 1000       416

mtCount = 4
MergeMT 1000000 X 1000  197234
MergeMT 100000 X 1000   17046
MergeMT 10000 X 1000    2087
MergeMT 1000 X 1000     684
MergeMT 100 X 1000      657
MergeMT 10 X 1000       596

因此,使用2个线程可使代码优化2倍以上。使用4个线程的影响更少,而使用8个线程几乎没有任何好处。使用16个线程甚至会降低性能,这是可以理解的。 (小的输入大小并不重要。我知道旋转一个新线程需要一些时间。)

知道我的计算机有4个物理核心和8个线程,我的问题是,为什么使用4或8个线程会提高性能呢?

1 个答案:

答案 0 :(得分:1)

因为合并排序包含2个主要部分:

  1. 递归地将两半排序
  2. 合并2个分类的一半

合并排序中的多线程非常有效,因为两个线程可以在第一步中异步执行2个不同的调用。但是,第二步不能通过多线程加快,因为它是一个线性过程,必须在单个线程上运行。第二步实际上需要花费大量时间。例如,最后一个(也是最大的)合并调用大约需要整个排序持续时间的三分之一。