我目前有一些问题需要理解为什么在某些情况下,Java中的并行化似乎效率不高.在下面的代码中,我构建了4个使用ThreadPool执行的相同任务.
在我的Core i5(2核,4线程)上,如果我将工作器数设置为1,则计算机需要大约5700ms并使用25%的处理器.如果我将工作器数量设置为4,那么我会观察100%的CPU使用率,但......计算时间是相同的:5700ms,而我预计它会低4倍.
为什么?这是正常的吗?
(当然我的真正任务更复杂,但这个例子似乎重现了这个问题).提前谢谢你的答案.
这是代码:
public class Test {
public static void main(String[] args) {
int nb_workers=1;
ExecutorService executor=Executors.newFixedThreadPool(nb_workers);
long tic=System.currentTimeMillis();
for(int i=0; i<4;i++){
WorkerTest wt=new WorkerTest();
executor.execute(wt);
}
executor.shutdown();
try {
executor.awaitTermination(1000, TimeUnit.SECONDS);
} catch (InterruptedException e) {e.printStackTrace();}
System.out.println(System.currentTimeMillis()-tic);
}
public static class WorkerTest implements Runnable {
@Override
public void run() {
double[] array=new double[10000000];
for (int i=0;i<array.length;i++){
array[i]=Math.tanh(Math.random());
}
}
}
}
Run Code Online (Sandbox Code Playgroud) 我正在寻找一种方法来列出正在运行的并行Java应用程序的所有同步调用,以便检测可伸缩性问题(就线程/核心而言)。据我了解,每次进入同步块时,机器都需要同步缓存。即使未通过输入同步区域来阻止正在运行的任务,这也会影响所有正在运行的CPU(以几种方式,例如内存带宽)。
我有一个大型应用程序,它在较高级别上并行化,即它具有并行执行的复杂任务。并行化的术语是,所有内核都处于负载状态,并且我没有阻塞线程。性能仍然无法随内核扩展,这可能有几个原因。我感兴趣的特定可能原因是,是否存在大量同步调用(例如,输入同步块,使用锁等)。
我想找出我的代码中(实际执行的)哪些地方进行了这样的同步调用,以及每次同步实际执行的频率。有很多引用的库,因此不可能仅对synced关键字或类似内容使用常规代码搜索,因为这将搜索很多从未执行的代码并带来很多误报。完美的解决方案是拥有一个探查器,该探查器列出所有已执行的同步位置和调用次数。但是,我尝试过的探查器仅允许对方法调用进行计数。因此,这里的问题是找到实际上相关的所有方法。
或者,如果我能找到某个入口点(主要方法)所引用的同步位置,这也将有所帮助。即,通过递归地遍历代码并检查所有引用的方法,类等进行此类同步。在这种情况下,以后可以使用常规探查器找出频率。
是否有工具或工作流,可以将上述任务归档用于较大的项目。
THX提前为您解答。