多线程环境中排序行为不稳定
本文关键字:不稳定 排序 环境 多线程 | 更新日期: 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