我的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分钟,你好?!?!)我的问题是为什么?
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);
}
}
答案 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);
}
请注意,您已阻止第一个Task
(future.get()
)的结果。与此同时,其他结果可能已经可用,但在第一次完成之前您无法看到它们。请使用CompletionService
来获得结果,以便更好地进行测量。这并不重要,因为您希望在结束计时器之前完成所有线程。
另一点:阻止I / O是关键。如果任务在I / O,网络等上被阻止,那么你拥有多少核心并不重要。现代处理器具有什么是超线程,如果当前正在执行线程块,它们可以运行等待运行的线程
因此,例如,如果我有16个内核并且我产生16个线程要求它们读取1 GB文件,那么仅仅通过拥有更多内核我不会获得任何性能改进。瓶颈是磁盘和内存。
答案 2 :(得分:1)
添加处理器会导致各种问题,但大多数问题与处理器之间的同步有关。文件系统中的任务级锁定等可能会成为一个问题,但更多的问题是核心之间的同步必须只是为了保持缓存一致性,跟踪已更改的页面等等。我不知道如何你拥有的每个芯片有很多核心(大约10年前放弃跟踪这些东西),但通常一旦开始同步片外性能就会下降。
我将补充一点,JVM可以在这里发挥重要作用。需要仔细的JVM设计以最大限度地减少共享(和经常更新的)缓存行的数量,并且需要花费大量精力才能使GC在多核环境中高效工作。