Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么java编译上的并行执行时间呈线性增长_Java_Linux_Linux Kernel_Cpu_Javac - Fatal编程技术网

为什么java编译上的并行执行时间呈线性增长

为什么java编译上的并行执行时间呈线性增长,java,linux,linux-kernel,cpu,javac,Java,Linux,Linux Kernel,Cpu,Javac,当我们并行运行javac命令时,随着javac命令的每次增加,~1秒将被添加到所有要完成的javac命令中 为什么时间会呈线性增长? 所有javac进程在运行时是否都涉及到锁上的某种类型,如果是,如何克服它,以免在时间上出现线性增长 PS:我在上面的单核机器,双核机器,四核机器上试过,都表现出相同的行为 PS2:environmentRedHat7,JavaC1.7.079java编译器已经在处理跨可用处理器的工作,即使只编译一个文件。因此,您自己并行运行单独的编译器实例不会产生预期的性能提升

当我们并行运行
javac
命令时,随着
javac
命令的每次增加,
~1秒
将被添加到所有要完成的
javac
命令中

为什么时间会呈线性增长?

所有
javac
进程在运行时是否都涉及到
锁上的某种类型,如果是,如何克服它,以免在时间上出现线性增长


PS:我在上面的
单核机器
双核机器
四核机器
上试过,都表现出相同的行为


PS2:environment
RedHat7
JavaC1.7.079
java编译器已经在处理跨可用处理器的工作,即使只编译一个文件。因此,您自己并行运行单独的编译器实例不会产生预期的性能提升

为了演示这一点,我在一个名为
Main1.java
的文件中生成了一个大型(100万行,10000个方法)java程序。然后通过
Main8.java
Main2.java
的形式制作其他副本。编译时间如下:

单文件编译:

time javac Main.java                                      --> 0m1.050s
time javac Main.java & javac Main.java                    --> 0m1.808s
time javac Main.java & javac Main.java & javac Main.java  --> 0m2.690s
time javac Main.java & ... 8 time                         --> 0m8.309s
top
中查看此单个文件的编译显示,处理器使用率大多在200-400%范围内(表示多个CPU使用率,每个CPU 100%),偶尔在700%范围内出现峰值(由于有8个处理器,因此此机器上的最大值为800%)

接下来,同时显示两个文件:

time javac Main1.java &    --> (real) 11.6 sec
time javac Main1.java &    --> (real) 14.5 sec
time javac Main2.java &    --> (real) 14.8 sec
time javac Main1.java &    --> (real) 24.2 sec
time javac Main2.java &    --> (real) 24.6 sec
time javac Main3.java &    --> (real) 25.0 sec
time javac Main4.java &    --> (real) 25.0 sec
因此,编译两个只需14.8秒,而编译一个只需11.6秒。这绝对是非线性的。当它们运行时,通过查看
top
可以清楚地看出,每个java编译器一次最多只利用四个CPU(偶尔峰值更高)。因此,这两个编译器在8个CPU上运行,大部分是并行的

接下来,同时显示四个文件:

time javac Main1.java &    --> (real) 11.6 sec
time javac Main1.java &    --> (real) 14.5 sec
time javac Main2.java &    --> (real) 14.8 sec
time javac Main1.java &    --> (real) 24.2 sec
time javac Main2.java &    --> (real) 24.6 sec
time javac Main3.java &    --> (real) 25.0 sec
time javac Main4.java &    --> (real) 25.0 sec
好了,我们撞到墙了。我们再也不能使编译器并行化了。四个文件用了25秒,两个文件用了14.8秒。有一点优化,但它主要是一个线性时间增加

最后,八个同时:

time javac Main1.java &    --> (real) 11.6 sec
time javac Main1.java &    --> (real) 14.5 sec
time javac Main2.java &    --> (real) 14.8 sec
time javac Main1.java &    --> (real) 24.2 sec
time javac Main2.java &    --> (real) 24.6 sec
time javac Main3.java &    --> (real) 25.0 sec
time javac Main4.java &    --> (real) 25.0 sec
这实际上比线性的要差一点,因为八个只花了54.6秒,而四个只花了25.0秒

因此,我认为这一切的好处在于相信编译器会在可用CPU资源范围内优化您所做的工作,并且手动添加额外的并行化的好处有限(如果有的话)

编辑:

作为参考,我在Oracle的bug数据库中找到了两条关于增强javac以利用多处理器的信息:

  • --原始投诉,最终被标记为以下内容的副本:
  • --建议解决方案,根据“解决日期”,似乎在2008年6月12日添加了javac中的多处理器支持

很容易被I/O绑定,而不是CPU绑定。关于如何确认其io绑定。。。看起来确实如此,因为我们的数据非常小,所以
javac
需要文件。我想你可以用RAM磁盘。我还要确保
Main.java
很大,所以您实际上是在检查编译与加载/保存。但当然,真正的问题是:你想优化什么?因为如果是整个过程,I/O是一个重要的因素,你不想测试它。至少在上面的测试中,文件“Main.java”在处理过程中可能会被javac锁定。我想您已经用不同的文件进行了测试?您没有提到您的编译器和构建系统。请参阅很好的解释,但如果我们采用8 hello world java(与您的相反)文件编译,然后在8核机器上并行使用8 javac,那么它应该在1秒内完成。。。。对吗?@user2410148:使用一个小的“helloworld”文件,我得到了以下编译时间:1用了0.32秒;2次为0.39秒;4次为0.54秒;第8节花了1.02秒。它似乎遵循相同的模式,将其拆分为两个并行编译,但尝试执行四个或八个编译时,时间的线性增加。我认为同样的概念也适用于小规模:让编译器为您执行并行化。我不认为您的结论是正确的。为了证明你的观点,你不应该计时编译1-8系列需要多长时间吗?否则,您将比较两种不同的工作量。据我估计,我可以启动javac并等待88秒,也可以从命令行并行化它并等待55秒。我的大多数java文件都在500行范围内,我猜javac在较小的文件/类中使用多个内核会比较困难。我并不是说16000并行javac是理想的解决方案,但我不同意“只要有信心”的建议。@Ryan:我的分析是为了证明javac确实是多线程的,并且在跨可用处理器分配工作方面做得不错。这并不意味着在某些情况下,您无法通过并行运行多个实例来获得更好的性能,但您不应该像询问者所期望的那样期望时间/N类型的改进。FWIW,我连续运行了八次编译,耗时89秒。然后尝试了一个单独的
javac*.java
,耗时56秒,与并行运行的54秒非常接近。另请参阅我之前的评论-较小的文件会产生类似的结果。
然后尝试了一个javac*.java,耗时56秒
这有助于证明您的观点。