增加核心数时降低性能

时间:2013-05-15 17:26:50

标签: java multithreading performance optimization concurrency

我的Mac装有16个核心。

System.out.println(Runtime.getRuntime().availableProcessors());  //16

我正在运行下面的代码,以了解使用我的核心的有效性。线程'CountFileLineThread'只计算文件中的行数(文件夹中有133个文件)

我在这条线上做笔记:

ExecutorService es = Executors.newFixedThreadPool(NUM_CORES);

NUM_CORES介于1到16之间。

您将从下面的结果中注意到,上述5个核心的性能开始下降。我不希望6芯及以上的产品“收益递减”(btw,7芯需要超过22分钟,你好?!?!)我的问题是为什么?

enter image description here

public class TestCores
{   
  public static void main(String args[]) throws Exception
  {
    long start = System.currentTimeMillis();
    System.out.println("START");

    int NUM_CORES = 1;

    List<File> files = Util.getFiles("/Users/adhg/Desktop/DEST/");
    System.out.println("total files: "+files.size());
    ExecutorService es = Executors.newFixedThreadPool(NUM_CORES);
    List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
    for (File file : files)
    {
        Future<Integer> future = es.submit(new CountFileLineThread(file));
        futures.add(future);
    }

    Integer total = 0;

    for (Future<Integer> future : futures)
    {
        Integer result = future.get();
        total+=result;
        System.out.println("result :"+result);

    }

    System.out.println("----->"+total);

    long end = System.currentTimeMillis();
    System.out.println("END. "+(end-start)/1000.0);
}
}

3 个答案:

答案 0 :(得分:19)

我添加了这个作为评论,但我会把它作为答案扔在那里。因为您的测试正在进行文件I / O,所以您可能在第6个线程中遇到了一点,您现在正在执行过多的I / O,从而减慢了所有内容的速度。如果你真的想看到你拥有的16个内核的好处,你应该重新编写文件读取线程以使用非阻塞I / O.

答案 1 :(得分:5)

我的预感是,您可能会对磁盘I / O造成太大负担,导致速度下降!请参阅“活动监视器”中的I / O性能(如果您使用的是OSX)。在Linux上,使用vmstat命令了解发生了什么。 [如果你看到很多交换或高速读取/ s和写入/ s那么你去]


我注意到的一些事情:

CountFileLineThread不在代码中。请把它放在一起,这样我们就可以确切地看到发生了什么。

接下来,

for (Future<Integer> future : futures)
{
    Integer result = future.get();
    total+=result;
    System.out.println("result :"+result);

}

请注意,您已阻止第一个Taskfuture.get())的结果。与此同时,其他结果可能已经可用,但在第一次完成之前您无法看到它们。请使用CompletionService来获得结果,以便更好地进行测量。这并不重要,因为您希望在结束计时器之前完成所有线程。

另一点:阻止I / O是关键。如果任务在I / O,网络等上被阻止,那么你拥有多少核心并不重要。现代处理器具有什么是超线程,如果当前正在执行线程块,它们可以运行等待运行的线程

因此,例如,如果我有16个内核并且我产生16个线程要求它们读取1 GB文件,那么仅仅通过拥有更多内核我不会获得任何性能改进。瓶颈是磁盘和内存。

答案 2 :(得分:1)

添加处理器会导致各种问题,但大多数问题与处理器之间的同步有关。文件系统中的任务级锁定等可能会成为一个问题,但更多的问题是核心之间的同步必须只是为了保持缓存一致性,跟踪已更改的页面等等。我不知道如何你拥有的每个芯片有很多核心(大约10年前放弃跟踪这些东西),但通常一旦开始同步片外性能就会下降。

我将补充一点,JVM可以在这里发挥重要作用。需要仔细的JVM设计以最大限度地减少共享(和经常更新的)缓存行的数量,并且需要花费大量精力才能使GC在多核环境中高效工作。