Java:通过多线程并行化快速排序
|
我正在尝试在 Java中并行化算法.我从合并排序开始,并在 question中发布了我的尝试.我修改后的尝试在下面的代码中,我现在尝试并行化快速排序. 在我的多线程实现或解决此问题的方法中是否存在任何新手错误?如果不是,我不应期望在双核上的顺序算法和并行算法之间的速度增加超过32%(参见底部的时间)? 这是多线程算法: public class ThreadedQuick extends Thread
{
final int MAX_THREADS = Runtime.getRuntime().availableProcessors();
CountDownLatch doneSignal;
static int num_threads = 1;
int[] my_array;
int start,end;
public ThreadedQuick(CountDownLatch doneSignal,int[] array,int start,int end) {
this.my_array = array;
this.start = start;
this.end = end;
this.doneSignal = doneSignal;
}
public static void reset() {
num_threads = 1;
}
public void run() {
quicksort(my_array,start,end);
doneSignal.countDown();
num_threads--;
}
public void quicksort(int[] array,int end) {
int len = end-start+1;
if (len <= 1)
return;
int pivot_index = medianOfThree(array,end);
int pivotValue = array[pivot_index];
swap(array,pivot_index,end);
int storeIndex = start;
for (int i = start; i < end; i++) {
if (array[i] <= pivotValue) {
swap(array,i,storeIndex);
storeIndex++;
}
}
swap(array,storeIndex,end);
if (num_threads < MAX_THREADS) {
num_threads++;
CountDownLatch completionSignal = new CountDownLatch(1);
new ThreadedQuick(completionSignal,array,storeIndex - 1).start();
quicksort(array,storeIndex + 1,end);
try {
completionSignal.await(1000,TimeUnit.SECONDS);
} catch(Exception ex) {
ex.printStackTrace();
}
} else {
quicksort(array,storeIndex - 1);
quicksort(array,end);
}
}
}
以下是我的启动方式: ThreadedQuick.reset();
CountDownLatch completionSignal = new CountDownLatch(1);
new ThreadedQuick(completionSignal,array.length-1).start();
try {
completionSignal.await(1000,TimeUnit.SECONDS);
} catch(Exception ex){
ex.printStackTrace();
}
我针对Arrays.sort和类似的顺序快速排序算法对此进行了测试.以下是intel duel-core dell笔记本电脑的计时结果,只需几秒钟: 要素:500,000, 要素:1, 要素:2, 要素:4, 要素:8, 上面的每个数字是100次测试的平均时间,抛出3个最低和3个最高的情况.我使用Random.nextInt(Integer.MAX_VALUE)为每个测试生成一个数组,每10次测试使用相同的种子初始化一次.每个测试包括使用System.nanoTime对给定算法进行计时.平均后我舍入到小数点后六位.显然,我确实检查了每种是否有效. 如您所见,在每组测试中,顺序和线程案例之间的速度提高了约32%.正如我上面提到的,我不应该期待更多吗? 解决方法将numThreads设为静态可能会导致问题,很可能最终会在某些时候运行MAX_THREADS以上.可能你没有在性能上完全翻倍的原因是你的快速排序无法完全并行化.请注意,对quicksort的第一次调用将在初始线程中开始真正并行运行之前传递整个数组.在耕种到单独的线程时,还存在以上下文切换和模式转换的形式并行化算法的开销. 看看Fork / Join框架,这个问题可能非常适合那里. 关于实施的几点意见.实现Runnable而不是扩展Thread.只有在创建一些新版本的Thread类时,才应使用扩展线程.当你只想做一些并行运行的工作时,你最好使用Runnable.在运行Runnable的同时,您还可以扩展另一个类,从而为OO设计提供更大的灵活性.使用仅限于系统中可用线程数的线程池.也不要使用numThreads来决定是否分叉新线程.你可以预先计算出来.使用最小分区大小,即总阵列的大小除以可用的处理器数.就像是: public class ThreadedQuick implements Runnable {
public static final int MAX_THREADS = Runtime.getRuntime().availableProcessors();
static final ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
final int[] my_array;
final int start,end;
private final int minParitionSize;
public ThreadedQuick(int minParitionSize,int end) {
this.minParitionSize = minParitionSize;
this.my_array = array;
this.start = start;
this.end = end;
}
public void run() {
quicksort(my_array,end);
}
public void quicksort(int[] array,int end) {
int len = end - start + 1;
if (len <= 1)
return;
int pivot_index = medianOfThree(array,end);
int pivotValue = array[pivot_index];
swap(array,end);
int storeIndex = start;
for (int i = start; i < end; i++) {
if (array[i] <= pivotValue) {
swap(array,storeIndex);
storeIndex++;
}
}
swap(array,end);
if (len > minParitionSize) {
ThreadedQuick quick = new ThreadedQuick(minParitionSize,storeIndex - 1);
Future<?> future = executor.submit(quick);
quicksort(array,end);
try {
future.get(1000,TimeUnit.SECONDS);
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
quicksort(array,storeIndex - 1);
quicksort(array,end);
}
}
}
你可以这样做: ThreadedQuick quick = new ThreadedQuick(array / ThreadedQuick.MAX_THREADS,array.length - 1); quick.run(); 这将在同一个线程中启动排序,这可以避免在启动时出现不必要的线程跳转. 警告:不确定上面的实现会更快,因为我没有对它进行基准测试. (编辑:鄂州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- java – 由于任务尝试无法报告状态600秒而导致reduce失败.杀
- java – 检查Drools列表中的特定元素
- java导出数据库的全部表到excel
- java – Spring数据REST加入继承问题
- java-ee – 在maven-embedded-glassfish-plugin上的CDI注入
- Java SAXParser:不同于`localName`和`qName`
- Java 将文件转为字节数组知识总结及实例详解
- 多线程 – 信号量P和V操作是否为原子?
- java – 配置Spring Security以使用customPasswordAuthenti
- java – 在处理信息检索中面向行和面向列的数据库之间的区别
