多线程环境中的不稳定排序行为

时间:2014-04-11 12:05:10

标签: c# .net multithreading

我试图实现并行合并。我使用插入排序作为排序短切片的基本方法,我观察到奇怪的行为:插入排序随机无法正确排序并使切片部分未排序。它发生在不同的切片,切片内的不同点:没有图案。当我切换到顺序mergesort(没有线程)时,一切都很好,所以它显然连接到多线程和线程交错,但我无法猜出是什么问题。这是代码:

class MergeSort
{
    public void ParallelSort(int[] values)
    {
        int[] aux = new int[values.Length];
        Start = DateTime.Now.Ticks;

        int lo = 0;
        int hi = values.Length - 1;
        int mid = values.Length / 2;

        Sort(values, aux, lo, mid, hi);

        End = DateTime.Now.Ticks;
    }

    private void Sort(int[] values, int[] aux, int lo, int mid, int hi)
    {
        if (hi - lo > 32)
        {
            Parallel.Invoke(
                () => Sort(values, aux, lo, (mid + lo)/2, mid),
                () => Sort(values, aux, mid + 1, (hi + mid)/2, hi));
            Merge(values, aux, lo, mid, hi);

        }
        else
            InsertionSort.Sort(values, lo, hi);
    }
    private unsafe void Merge(int[] values, int[] aux, int lo, int mid, int hi)
    {
        Buffer.BlockCopy(values, sizeof(int)* lo, aux, sizeof(int) * lo, sizeof(int) * (hi-lo + 1));

        int i = lo;
        int j = mid+1;

        fixed (int* a = values, b = aux)
        {
            for (int k = lo; k <= hi; k++)
            {
                if (i > mid)
                    a[k] = b[j++];
                else if (j > hi)
                    a[k] = b[i++];
                else if (b[i] < b[j])
                    a[k] = b[i++];
                else
                    a[k] = b[j++];
            }
        }

    }
}

class InsertionSort
{
    public static unsafe void Sort(int[] values, int lo, int hi)
    {
        fixed (int* b = &values[0])
        {
            for (int i = lo+1; i <= hi; i++)
            {
                int tmp = b[i];
                int j;
                for (j = i; j > 0 && tmp < b[j - 1]; j--)
                    b[j] = b[j - 1];
                b[j] = tmp;
            }
        }
    }
}

这是插入排序的切片:

Thread 3 slice: 93-123 IsSorted: False
Thread 6 slice: 62-92 IsSorted: False
Thread 10 slice: 0-30 IsSorted: True
Thread 9 slice: 124-154 IsSorted: False
Thread 7 slice: 185-214 IsSorted: True
Thread 5 slice: 31-61 IsSorted: False
Thread 8 slice: 155-184 IsSorted: False
Thread 4 slice: 215-245 IsSorted: False

1 个答案:

答案 0 :(得分:0)

发现它:切片插入排序中的错误: 应该是

 for (j = i; j > lo && tmp < b[j - 1]; j--)

而不是

for (j = i; j > 0 && tmp < b[j - 1]; j--)

排序超越了lo-hi边界。

BTW,我在java中实现了相同的程序,java的fork / join排序速度是.Net的两倍。 Parallel.Invoke