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

本文关键字:不稳定 排序 环境 多线程 | 更新日期: 2023-09-27 17:57:50

I.m试图实现并行合并。我使用插入排序作为排序短切片的基本方法,并观察到奇怪的行为:插入排序随机无法正确排序,导致切片部分未排序。它发生在不同的切片中,切片中的不同点:没有模式。当我切换到顺序合并(无线程)时,一切都很好,所以它显然与多线程和线程交织有关,但我猜不出问题出在哪里。这是代码:

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

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

发现了:这是切片插入排序中的一个错误:应该是

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

而不是

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

排序超出了lo-hi边界。

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