为什么我的Parallel QuickSort方法比顺序方法慢?

时间:2012-10-16 00:23:44

标签: c# parallel-processing invoke quicksort

我是并行编程的新手,我不确定为什么QuickSortParallel方法比我的顺序版本慢(没有Parallel.Invoke)。我有一个锯齿状的数组,由我传递的十万个9位数字组成。不幸的是,当我使用QuickSortParallel方法时,它最终比顺序版本慢近5倍。

我可以做的不仅仅是在数据源上使用Parallel.Invoke吗?

    public static void QuickSort_Parallel<T>(T[] array2) where T : IComparable<T>
    {
        QuickSortParallel(array2, 0, array2.Length - 1);
    }

    private static void QuickSortParallel<T>(T[] array2, int left, int right)
        where T : IComparable<T>
    {
        if (left >= right)
        {
            return;
        }

        SwapElements(array2, left, (left + right) / 2); //median pivot
        int last = left;
        for (int current = left + 1; current <= right; ++current)
        {
            //CompareTo, compares current array index value with
            if (array2[current].CompareTo(array2[left]) < 0)
            {
                ++last;
                SwapElements(array2, last, current);
            }
        }

        SwapElements(array2, left, last);
        //Recursive
        //Executes each of the provided actions in parallel.
        Parallel.Invoke(
            () => QuickSortParallel(array2, left, last - 1),
            () => QuickSortParallel(array2, last + 1, right)
        );
    }

    static void SwapElements<T>(T[] array2, int i, int j)
    {
        T temp = array2[i];
        array2[i] = array2[j];
        array2[j] = temp;
    }

3 个答案:

答案 0 :(得分:2)

很可能,你的问题来自于线程的开销。

使用线程通常会使CPU密集型工作更快,但是启动一个新线程需要大量开销,如果你给太多线程太少工作,那么你可以让你的程序运行得更慢。

运行以下行时:

    Parallel.Invoke(
        () => QuickSortParallel(array2, left, last - 1),
        () => QuickSortParallel(array2, last + 1, right)
    );

...您可能导致当前线程产生另外两个线程(取决于Parallel.Invoke的实现方式)。如果我的心理数学是正确的(如果Parallel.Invoke确实创建了新的线程),那么你正在创建n * log(n)个线程 - 这是一个巨大的数字!

如果你想看到性能提升,你需要平衡线程数 - 更多并不总是更好。使用系统线程池限制线程数的好方法:

System.Threading.ThreadPool.QueueUserWorkItem(
        () => QuickSortParallel(array2, left, last - 1));
System.Threading.ThreadPool.QueueUserWorkItem(
        () => QuickSortParallel(array2, last + 1, right));

......或者其他类似的东西。如果您愿意,也可以实现自己的线程池。 一个

另一种选择是限制递归的深度,从而限制线程的数量。

答案 1 :(得分:2)

答案 2 :(得分:0)

围绕使用SwapElements方法的争论?尝试将SwapElements方法的逻辑直接放入方法/循环中,而不是调用它...这将允许它成为生成的每个并行线程上发生的事情的一部分,而不是潜在的瓶颈。看看那是不是什么......只是一个建议,但不确定它是否会证明是有用的。