java中快速排序的早期研究
我有一个问题,我不能-完全-缠绕我的头。我正在用一百万个整数进行快速排序和堆排序的比赛。每个排序算法将列表分成32个线程子部分,然后对它们进行排序,最后将每个已排序的子部分合并成一个连贯的整体(使用更多线程) 我不是使用快速排序对整个子数组进行排序,然后将整个内容推送到合并中,而是试图找到一种方法,使用快速排序找到最小值,并在整个部分排序之前推送该值。由于我实际上没有足够的内核来同时运行我所有的线程,我希望性能影响可以忽略不计,但我想测试一下这个理论 在我的4核机器上,heapsort和quicksort的时间大约为14秒加上或减去2秒。速度似乎取决于我首先运行的算法,即使我在排序之后洗牌 这是我现在的快速排序代码:java中快速排序的早期研究,java,multithreading,algorithm,sorting,Java,Multithreading,Algorithm,Sorting,我有一个问题,我不能-完全-缠绕我的头。我正在用一百万个整数进行快速排序和堆排序的比赛。每个排序算法将列表分成32个线程子部分,然后对它们进行排序,最后将每个已排序的子部分合并成一个连贯的整体(使用更多线程) 我不是使用快速排序对整个子数组进行排序,然后将整个内容推送到合并中,而是试图找到一种方法,使用快速排序找到最小值,并在整个部分排序之前推送该值。由于我实际上没有足够的内核来同时运行我所有的线程,我希望性能影响可以忽略不计,但我想测试一下这个理论 在我的4核机器上,heapsort和quic
//code borrowed from http://stackoverflow.com/questions/19124752/non-
//recursive-quicksort
public synchronized void qSort(PipedOutputStream pout, int start, int sz) {
Deque<int[]> stack = new ArrayDeque<int[]>();
int first = start;
int last = start + sz - 1;
if(first >= arr.length || last >= arr.length){
System.out.printf("\nSorting error: parameters out of bounds! Start %d, end %d \n", start, last);
return;
}
stack.push(new int[] {first, last});
while(!stack.isEmpty()) {
qsortStep(arr, stack);
}
try { out = new ObjectOutputStream ( pout ); }
catch (IOException e ) { e.printStackTrace(); }
while ( size >= 1 ) {
try {
// System.out.printf("sort is writing %d to pipe.\n", v );
out.writeObject( arr[start] );
out.flush( );
start++; size--;
} catch(IOException e ) { e.printStackTrace(); }
}
}
private synchronized void qsortStep(T[] list, Deque<int[]> stack) {
if(stack.isEmpty())
return;
int temp[] = stack.pop();
int first = temp[0];
int last = temp[1];
int boundLo = first;
int boundHi = last;
//Pivot can be optimized to median of quintiles to mitigate O(n^2) on sorted arrays.
int pivot = last;
/*int sz = last - first;
int pivots[] = {first, first+sz/5, first+2*sz/5, first+4*sz/5, last};
for(int i = 0; i < 5; i++)
for(int j = 4; j > i; j--)
if(arr[pivots[i]].compareTo(arr[pivots[j]]) > 0)
swap(pivots, i, j);*/
pivot = last;
while(first < last) {
//possible opportunity here for early min
if(list[first].compareTo(list[pivot]) >= 0) {
last--;
if(first != last)
swap(list, first, last);
swap(list, last, pivot);
pivot--;
}
else first++;
}
if(boundLo < (pivot - 1))
stack.add(new int[] {boundLo, pivot - 1});
if(boundHi > (pivot + 1))
stack.add(new int[] {pivot + 1, boundHi});
}
//从中借用的代码http://stackoverflow.com/questions/19124752/non-
//递归快速排序
公共同步void qSort(PipedOutputStream pout、int start、int sz){
Deque stack=new ArrayDeque();
int first=开始;
int last=start+sz-1;
如果(第一个>=arr.length | |最后一个>=arr.length){
System.out.printf(“\n设置错误:参数超出范围!开始%d,结束%d\n”,开始,最后一个);
返回;
}
push(新的int[]{first,last});
而(!stack.isEmpty()){
qsortStep(arr,stack);
}
试试{out=newObjectOutputStream(pout);}
catch(IOE异常){e.printStackTrace();}
而(大小>=1){
试一试{
//System.out.printf(“排序正在将%d写入管道。\n”,v);
out.writeObject(arr[start]);
out.flush();
开始++;大小--;
}catch(IOE异常){e.printStackTrace();}
}
}
私有同步的void qsortStep(T[]列表,数据堆栈){
if(stack.isEmpty())
返回;
int temp[]=stack.pop();
int first=temp[0];
int last=温度[1];
int boundLo=第一;
int boundHi=最后一个;
//Pivot可以优化为五分位数的中值,以减少排序数组上的O(n^2)。
int pivot=最后一个;
/*int sz=最后一个-第一个;
int pivots[]={first,first+sz/5,first+2*sz/5,first+4*sz/5,last};
对于(int i=0;i<5;i++)
对于(int j=4;j>i;j--)
如果(arr[pivots[i]].比较到(arr[pivots[j]]]>0)
交换(枢轴,i,j)*/
枢轴=最后一个;
while(第一次<最后一次){
//可能的机会在这里为早分钟
如果(列表[first].compareTo(列表[pivot])>=0){
最后--;
如果(第一个!=最后一个)
交换(列表、第一个、最后一个);
交换(列表、最后一个、轴心);
支点--;
}
else-first++;
}
如果(边界<(枢轴-1))
add(新的int[]{boundLo,pivot-1});
如果(边界>(枢轴+1))
add(新int[]{pivot+1,boundHi});
}
如果您真的想这样做,那么在循环数组时跟踪最小值,将其与最外层的一个元素交换(然后将其排除在进一步排序之外),并将该元素的位置通知另一个线程应该很简单。您将添加到quicksort中的开销可能会超过您从中获得的任何好处,但我可能错了。是的,您可以通过与当前将元素与轴心进行比较的相同方式比较元素来跟踪最小值(您可能希望存储最小值的索引,而不是最小值的索引,因为您需要索引来交换它)。我的意思是,您可以使用与pivot大致相同的技术来比较元素。因此,您需要同时跟踪最小值和pivot。(对于多线程来说,一百万个项目看起来很少,q-排序的大小也很高。)我会尝试作为流的替代。(我会避免在循环中建立一个try
-块。只需在每个线程的最外层创建try-catch
,并根据需要在下面声明抛出。)推送[lo,hi]
而不是仅仅两个int
s查看工程(并为new ArrayDeque()
指定一个使大小调整变得不可能的大小)。尝试“输出boundLo
和pivot
”当不需要对该范围进行排序时。一台4核机器很难足够旧到需要几秒钟来堆出一百万个int
s:你在做什么?(PipedOut/InputStream
?)如果你真的想,在循环数组时跟踪最小值应该很简单,用最外层的元素之一交换它(然后将其从进一步排序中排除)并将该元素的位置通知另一个线程。您将添加到快速排序中的开销可能会超过您从中获得的任何好处,但我可能错了。是的,您可以通过与当前将元素与轴心进行比较的相同方式比较元素来跟踪最小值(您可能希望存储最小值的索引,而不是最小值的索引,因为您需要索引来交换它)。我的意思是,您可以使用与pivot大致相同的技术来比较元素。因此,您需要同时跟踪最小值和pivot。(对于多线程来说,一百万个项目看起来很少,q-排序的大小也很高。)我会尝试作为流的替代。(我会避免在循环中建立一个try
-块。只需在每个线程的最外层创建try-catch
,并根据需要在下面声明抛出。)推送[lo,hi]
而不是仅仅两个int
s查看工程(并为new ArrayDeque()