我的搜索过程通过多线程变慢

时间:2017-07-13 17:08:19

标签: java multithreading matrix

我是并行编程的新手。我试图做一个练习的方法,但每次正常过程花费的时间少于执行中的并行过程。我的实施有问题吗?

    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);
                }
            }
        }


    }

}

这是使用Parallel选项的尝试

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

由于

1 个答案:

答案 0 :(得分:2)

你在一个单独的线程中运行一个非常简单快速的执行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,您将得到以下结果:

  

现在并行1580 | 1:206

     

现在正常1580 | 1:3162

没有Thread.sleep(线程开销比搜索要大得多):

  

NOW parallel 1580 | 1:46

     

现在正常1580 | 1:9