我对并行编程很陌生。我试图做一种练习方法,但每次正常过程比执行中的并行过程花费的时间更少。我的实现有问题吗?
public class normalExecutor {
public normalExecutor() {
}
public int[][] matriz = new int[3000][3000];
public void search() {
long startTime = System.currentTimeMillis();
int biggest = 0;
matriz[800][800] = 9;
for (int i = 0 ; i < 3000; i++) {
for (int j = 0; j < 3000; j++) {
if(matriz[i][j] == 9) {
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("NOW normal "+ i + "|" + j + ": " + elapsedTime);
}
}
}
}
}
这是使用并行选项的尝试
public class ParallelExecutor {
final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final List<Future<?>> futures = new ArrayList<>();
public int[][] matriz = new int[3000][3000];
public ParallelExecutor() {
}
public void parallelSearch() {
long startTime = System.currentTimeMillis();
matriz[800][800] = 9;
for (int i = 0 ; i < 3000; i++) {
for (int j = 0; j < 3000; j++) {
int x = i;
int z = j;
Future<?> future = executor.submit(() -> {
if(matriz[x][z] == 9) {
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("NOW parallel "+ x + "|" + z+ ": " + elapsedTime);
}
});
}
}
}
}
即使有时并行打印首先打印,输出总是像这样
NOW parallel 800|800: 3089
NOW normal 800|800: 21
谢谢
最佳答案
您在一个单独的线程中运行了 900 万次非常简单且快速的执行。只是创建 runnable 来包装代码所需的时间,ExecutorService
等待可用线程并在其中运行代码所花费的时间会大得多。
正确的方法是将 3kx3k 矩阵的迭代拆分为单独的线程。例如,给每个线程 500 行来处理。这样您将有大约 6 个线程并行处理独立数据。
我更改了您的代码,以显示当您处理每行甚至需要 2 毫秒的执行时,并行处理的速度相对较快。
但我必须做出两处改变。
首先,我将带有 9 的单元格移到了矩阵的中间,这样在正常搜索中就很难快速找到它。
其次,我添加了 Thread.sleep
来模拟长时间运行的执行,以证明并行处理的合理性。
final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final List<Future<?>> futures = new ArrayList<>();
public int[][] matriz = new int[3000][3000];
public void parallelSearch() {
long startTime = System.currentTimeMillis();
matriz[1580][1] = 9;
executor.submit( () -> search( 0, 500, startTime) );
executor.submit( () -> search( 500, 1000, startTime) );
executor.submit( () -> search( 1000, 1500, startTime) );
executor.submit( () -> search( 1500, 2000, startTime) );
executor.submit( () -> search( 2000, 2500, startTime) );
executor.submit( () -> search( 2500, 3000, startTime) );
}
public void search(int startRow, int endRow, long startTime){
for (int i = startRow ; i < endRow; i++) {
//add some execution time to justify parallel processing
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int j = 0; j < 3000; j++) {
int x = i;
int z = j;
if(matriz[x][z] == 9) {
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("NOW parallel "+ x + "|" + z+ ": " + elapsedTime);
}
}
}
}
public void search() {
long startTime = System.currentTimeMillis();
int biggest = 0;
for (int i = 0 ; i < 3000; i++) {
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int j = 0; j < 3000; j++) {
if( matriz[i][j] == 9 ) {
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("NOW normal "+ i + "|" + j + ": " + elapsedTime);
}
}
}
}
使用上面的代码并使用Thread.sleep
,您将得到以下结果:
NOW parallel 1580|1: 206
NOW normal 1580|1: 3162
没有Thread.sleep
(线程开销比搜索大得多):
NOW parallel 1580|1: 46
NOW normal 1580|1: 9
关于java - 我的搜索过程通过多线程变得更慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45087077/