所以这是我的代码:
/**
* Created by TianTuoYou on 4/7/16.
*/
public class MTQuickSort implements SortingAlgorithm {
private int threadAmount = 1;
@Override
public void sort(int[] list) {
QuickSortRunnable quickSortRunnable = new QuickSortRunnable(list, 0, list.length - 1);
quickSortRunnable.run();
}
private class QuickSortRunnable implements Runnable {
private int[] list;
private int low;
private int high;
public QuickSortRunnable(int[] list, int low, int high) {
this.list = list;
this.low = low;
this.high = high;
}
@Override
public void run() {
quickSort(list, low, high);
}
private void quickSort(int[] list, int low, int high) {
if (low < high) {
int pivotLocation = partition(list, low, high);
if (threadAmount < 5) {
Thread thread1 = new Thread(new QuickSortRunnable(list, low, pivotLocation - 1));
thread1.start();
Thread thread2 = new Thread(new QuickSortRunnable(list, pivotLocation + 1, high));
thread2.start();
threadAmount+=2;
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
quickSort(list, low, pivotLocation - 1);
quickSort(list, pivotLocation + 1, high);
}
}
}
private int partition(int[] list, int low, int high) {
int pivot = list[high];
int leftWall = low;
int temp;
for (int i = low; i < high; i ++) {
if (list[i] <= pivot) {
leftWall ++;
temp = list[leftWall - 1];
list[leftWall - 1] = list[i];
list[i] = temp;
}
}
temp = list[leftWall];
list[leftWall] = list[high];
list[high] = temp;
return leftWall;
}
}
}
在我对此算法进行测试后,我发现无论输入多大,它都没有显示比单线程快速排序更快的速度,在大多数情况下它甚至更慢。任何人都可以解释原因吗?
答案 0 :(得分:0)
partition
出现在主排序线程中。您partition
的实现是O(N),这是分拣成本的主要部分,并且通过并行化其余部分可以消除任何实际收益。
在partition
之后,您创建了记录(N)个其他线程以在每个线程内重新分区数据,将O(N * log N)排序转换为O(N ^ log N) - 注意从乘以到到的权力的变化。请注意,您有一个竞争条件允许最多创建9个线程,尽管您最有可能看到使用5个或7个,其中9个非常罕见。
由于每个线程层都有效地重新排序整个列表,因此最终可能会执行至少O(N^5)
个移动/比较操作。对于只需要排序的一百个元素,这可能需要2000万倍的实际快速排序操作。
请注意,无论您拥有多少内核,您都不可能超越内置的Java运行时排序 - 大多数Java运行时都是用C / C ++编写的,以避免像Java内存模型一样多的开销。可能。对于诸如整数的小块数组尤其如此。只要你有能力,就使用运行时排序。
如果您只是想出于教育目的而这样做,那么您将需要专注于并行化partition
操作,并减少其中发生的掉期数量,因为这是您的大部分成本。