Java多线程矢量添加

时间:2017-01-03 16:02:59

标签: java multithreading parallel-processing thread-safety

我正在尝试熟悉java多线程应用程序。我试着想到一个可以很好地并行化的简单应用程序。我认为添加矢量将是一个很好的应用程序。 但是,当我的Linux服务器(有4个核心)上运行时,我没有加速。在4,2,1个线程上执行的时间大致相同。

以下是我提出的代码:

   public static void main(String[]args)throws InterruptedException{

    final int threads = Integer.parseInt(args[0]);
    final int length= Integer.parseInt(args[1]);
    final int balk=(length/threads);
    Thread[]th = new Thread[threads];

    final double[]result =new double[length];

    final double[]array1=getRandomArray(length);
    final double[]array2=getRandomArray(length);

    long startingTime =System.nanoTime();
    for(int i=0;i<threads;i++){
        final int current=i;
        th[i]=new Thread(()->{
           for(int k=current*balk;k<(current+1)*balk;k++){
               result[k]=array1[k]+array2[k];
           }
        });
        th[i].start();
    }
    for(int i=0;i<threads;i++){
        th[i].join();
    }
    System.out.println("Time needed: "+(System.nanoTime()-startingTime));


}

length始终是线程的倍数,getRandomArray()创建一个0到1之间的双精度随机数组。

1-Thread的执行时间:84579446ns
2线程的执行时间:74211325ns
4线程的执行时间:89215100ns
长度= 10000000

以下是getRandomArray()的代码:

    private static double[]getRandomArray(int length){
    Random random =new Random();
    double[]array= new double[length];
    for(int i=0;i<length;i++){
        array[i]=random.nextDouble();
    }
    return array;
}

我将不胜感激。

2 个答案:

答案 0 :(得分:2)

以下代码可以观察到差异。试试吧。

public static void main(String[]args)throws InterruptedException{

    for(int z = 0; z < 10; z++) {

        final int threads = 1;
        final int length= 100_000_000;
        final int balk=(length/threads);
        Thread[]th = new Thread[threads];

        final boolean[]result =new boolean[length];

        final boolean[]array1=getRandomArray(length);
        final boolean[]array2=getRandomArray(length);

        long startingTime =System.nanoTime();
        for(int i=0;i<threads;i++){
            final int current=i;
            th[i]=new Thread(()->{
                for(int k=current*balk;k<(current+1)*balk;k++){
                    result[k]=array1[k] | array2[k];
                }
            });
            th[i].start();
        }
        for(int i=0;i<threads;i++){
            th[i].join();
        }

        System.out.println("Time needed: "+(System.nanoTime()-startingTime)*1.0/1000/1000);

        boolean x = false;
        for(boolean d : result) {
            x |= d;
        }
        System.out.println(x);
    }
}

首先,您需要预热代码。这样您就可以测量编译的代码。前两次迭代具有相同(近似)的时间,但下一次迭代将有所不同。此外,我将double更改为boolean,因为我的机器没有太多内存。这允许我分配一个巨大的数组,它也会使工作更耗费CPU。

评论中有一个链接。我建议你阅读它。

答案 1 :(得分:2)

大家好,如果您正在尝试查看核心共享的工作方式,您可以为所有核心做出非常简单的任务,但要让它们不断地在不同线程之间共享的东西上工作(基本上是为了模拟例如合并排序,线程正在处理复杂的事情,并在很短的时间内使用共享资源。使用你的代码我做了这样的事情。在这种情况下,你应该看到几乎正好2倍的加速和4倍的加速。

public static void main(String[]args)throws InterruptedException{
        for(int a=0; a<5; a++) {
            final int threads = 2;
            final int length = 10;
            final int balk = (length / threads);
            Thread[] th = new Thread[threads];
            System.out.println(Runtime.getRuntime().availableProcessors());
            final double[] result = new double[length];

            final double[] array1 = getRandomArray(length);
            final double[] array2 = getRandomArray(length);

            long startingTime = System.nanoTime();
            for (int i = 0; i < threads; i++) {
                final int current = i;
                th[i] = new Thread(() -> {
                    Random random = new Random();
                    int meaningless = 0;
                    for (int k = current * balk; k < (current + 1) * balk; k++) {
                        result[k] = array1[k] + array2[k];
                        for (int j = 0; j < 10000000; j++) {
                            meaningless+=random.nextInt(10);
                        }
                    }
                });
                th[i].start();
            }
            for (int i = 0; i < threads; i++) {
                th[i].join();
            }
            System.out.println("Time needed: " + ((System.nanoTime() - startingTime) * 1.0) / 1000000000 + " s");

        }
    }

你会看到,在你的代码中,大部分时间都是通过构建大表来消耗的,然后线程执行速度非常快,他们的工作速度太快,以至于你的时间计算错误,因为大部分时间都是通过创建线程来消耗的。当我调用在预先计算的循环上工作的代码时:

    long startingTime =System.nanoTime();
    for(int k=0; k<length; k++){
        result[k]=array1[k]|array2[k];
    }
    System.out.println("Time needed: "+(System.nanoTime()-startingTime));

它比使用2个线程的代码快两倍。我希望你理解我在这种情况下的意思,并且当我给我的线程做更多毫无意义的工作时,我会明白我的观点。