使用YourKit,我计量了一个应用程序,并确定了主CPU接收器。我将计算结构化为通过具有固定数量线程的ExecutorService并行化。
在24核计算机上,添加线程的好处非常快4以上。所以,我想,这里肯定会有一些争用或锁定,或IO延迟等等。
好的,我打开了YourKit的'Monitor Usage'功能,并且工作线程中显示的阻塞时间量非常小。通过眼线状态图表,工作线程几乎全部为“绿色”(正在运行),而不是黄色(等待)或红色(被阻止)。
CPU分析仍然显示96%的时间位于工作线程内的调用树中。
所以有些东西正在耗尽实时。可能是调度开销吗?
在伪代码中,您可以将其建模为:
loop over blobs:
submit tasks for a blob via invokeAll of executor
do some single-threaded processing on the results
end loop over blobs
在测试运行中,有大约680个blob,以及~13个任务/ blob。因此每个线程(假设四个)每个blob大约发送3次。
硬件:我在我的MacBook pro上小规模地运行测试,然后在一个大胖子戴尔:Linux上的hwinfo报告24个不同的项目--cpu,由组成Intel(R) Xeon(R) CPU X5680 @ 3.33GHz
英特尔的网站告诉我每个都有6个核心,12个线程,我怀疑我有4个核心。
答案 0 :(得分:2)
假设您有4个核心,每个核心有8个逻辑线程,这意味着您有4个真正的处理单元,可以在32个线程之间共享。它还意味着当你在同一个内核上有2-8个活动线程时,它们必须争夺资源,例如CPU管道和指令和数据缓存。
当您有许多必须等待磁盘或网络IO等外部资源的线程时,这种方法效果最佳。如果你有CPU密集型进程,你可能会发现每个核心一个线程将使用你拥有的所有CPU能力。
我编写了一个库,支持为linux和windows分配线程和内核。如果你有Solaris,它可能很容易移植,因为它支持JNI posix调用和JNA调用。
答案 1 :(得分:1)
这很可能不是争用,但如果没有更多细节,很难说。分析结果可能会产生误导,因为Java会在线程或网络I / O上阻止线程报告为RUNNABLE。 Yourkit仍将其视为CPU时间。
最好的办法是打开CPU分析,深入了解工作线程中的时间。如果它主要在java.io类中结束,那么您仍然会遇到磁盘或网络延迟。
答案 2 :(得分:0)
您还没有完全并行化处理。你可能没有提交下一个blob,直到前一个blob的结果完成,因此没有并行处理。
如果可以,请尝试这种方式:
for each blob{
create a runnable for blob process name it blobProcessor;
create a runnable for blob results name it resultsProcessor;
submit blobProcessor;
before blobProcessor finishes, submit resultsProcessor;
}
也:
请看一下使用光纤提供无线并发的JetLang。