为什么IntStream.range(0,100000).parallel()。foreach花费的时间比正常for循环的时间长

问题描述 投票:1回答:1

[我刚刚开始学习Java中的Streams和并行,我想知道为什么普通的for循环比将IntStream并行添加项目到数组所需的时间少。

package parallel;

import java.util.stream.IntStream;

public class Parallel {

    public static void main(String[] args) {
         final int[] intArray = new int[100000];
        long startTime = System.currentTimeMillis(); 
        IntStream.range(0, 100000).parallel().forEach(i ->  intArray[i]=i);
        long endTime = System.currentTimeMillis();
        System.out.println("Parallel time: " + (endTime-startTime));
        final int[] intArray2 = new int[100000];
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        startTime = System.currentTimeMillis();
        for(int i = 0; i < 100000; i++){
            intArray2[i] = i;
        }
        endTime = System.currentTimeMillis();
        System.out.println("Non parallel time: " + (endTime-startTime));
    }
}

获得这样的结果。

平行时间:110

非并行时间:7

java benchmarking java-stream
1个回答
5
投票

您对每个元素执行的操作非常简单,这只是一个分配,非常快。在并行版本中,启动多个处理操作的线程会产生大量开销。仅此一项操作所花的时间可能要比非并行应用时进行非常简单的操作所花费的时间更长。

此外,在非并行版本中,值以非常线性的方式写入数组,该CPU体系结构已经有相当长的一段时间对单威胁/单核进行了优化,编译器和中间编译器也是如此(它们会转换代码,例如C组装)。但是在并行版本中,当每个线程尝试写入同一数组时(尽管位置不同,但可能仍在同一缓存行上),当多个线程访问数组的不同部分时,您可能会遇到冲突。可能还会导致缓存未命中,这会使事情变慢。

[使用更昂贵的操作,与总成本相比,并行版本的开销变得更小,最终将比非并行情况更快地执行。

© www.soinside.com 2019 - 2024. All rights reserved.