java - 我的搜索过程通过多线程变得更慢

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


    }

}

这是使用并行选项的尝试

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/

相关文章:

java - java.io 包中的缓冲如何优化性能

java - Apache Kafka : 3 partitions, 消费者组中有3个消费者,每个消费者应该是多线程的

java - java中多线程构造不可变树的算法

algorithm - 通过添加来自标准基的向量构建满秩矩阵

Python:在 numpy 中定义矩阵的内存优化方式

r - 使用回收创建矩阵

java - 从 Java 使用宏读取 Excel

java - 对对象数组进行排序时出现类型错误

java - 选择 Spinner Item 来更改 TextView 中的文本?

python - 在 Python 中给事件线程一个唯一的编号