我一直在使用此代码:
library(parallel)
cl <- makeCluster( detectCores() - 1)
clusterCall(cl, function(){library(imager)})
然后我有一个包装函数看起来像这样:
d <- matrix #Loading a batch of data into a matrix
res <- parApply(cl, d, 1, FUN, ...)
# Upload `res` somewhere
我在笔记本上测试了8核(4核,超线程)。当我在50,000行,800列,矩阵上运行时,需要177.5秒来完成,并且大多数时间内7个核心保持在接近100%(根据顶部),然后它在那里坐了最后15个约秒,我想这是合并结果。根据{{1}},用户时间为14秒,因此匹配。
现在我在EC2上运行,这是一款36核的c4.8x大型机,而且我看到它几乎所有的时间只用一个100%的核心。更准确地说:使用所有核心大约需要10-20秒的爆发,然后大约90秒只有一个核心100%(由R使用),然后大约45秒的其他东西(我保存结果和加载下一批数据)。我做的是40,000行,800列的批次。
根据上图,长期负荷平均值在5.00左右徘徊。
这看起来合情合理吗?或者是否存在R并行性花费更多时间进行通信开销的问题,我应该限制为例如16核。这里有任何经验法则吗?
参考:CPU spec我正在使用&#34; Linux 4.4.5-15.26.amzn1.x86_64(amd64)&#34;。 R版本3.2.2(2015-08-14)
更新:我尝试了16个内核。对于最小的数据,运行时间从13.9s增加到18.3s。对于中型数据:
system.time()
即。 开销部分需要相同的时间,但并行位的核心数量较少,因此需要更长的时间,因此总体上需要更长的时间。
我也尝试使用With 16 cores:
user system elapsed
30.424 0.580 60.034
With 35 cores:
user system elapsed
30.220 0.604 54.395
,正如评论中所建议的那样。它看起来确实有点快(在我试过的特定测试数据上就像330s和360s一样),但那是在我的笔记本上,其他过程或过热会影响结果。所以,我还没有得出任何结论。
答案 0 :(得分:2)
没有有用的经验法则 - 并行任务最适合的核心数完全由所述任务决定。有关更一般性的讨论,请参阅Gustafson’s law。
您在代码中看到的高单核部分可能来自算法的结束阶段(“连接”阶段),其中并行结果被整理为单个数据结构。由于这远远超过并行计算阶段,这可能确实表明较少的核可能是有益的。
答案 1 :(得分:2)
我补充一点,如果您不了解R中并行计算的这个优秀资源,您可能会发现阅读Norman Matloff最近出版的书Parallel Computing for Data Science: With Examples in R, C++ and CUDA
非常有用。我强烈推荐它(我学到了很多,不是来自CS背景)。
本书深入回答了你的问题(具体见第2章)。本书高度概述了导致并行程序瓶颈的开销原因。
引用第2.1节,其中隐含地部分回答了您的问题:
并行编程有两个主要的性能问题:
通信开销:通常必须传回数据 进程之间。这需要时间,这可能会花费很多时间 在表现上。此外,这些过程可以相互促进 如果他们都试图一次访问相同的数据。他们可以在什么时候碰撞 试图访问相同的通信通道,相同的内存 模块,等等。这是另一种速度上的挫折。术语粒度 用于粗略地指代计算与开销之比。 大粒度或粗粒度算法涉及足够大的块 计算,开销不是很大的问题。在 细粒度算法,我们真的需要避免开销 可能。
^当开销很高时,手头问题的核心越少,总计算时间就越短。
负载均衡:如上一章所述,如果我们不是 小心我们将工作分配给流程的方式,我们冒险 为某些人分配的工作量远远多于其他人。这妥协了 性能,因为它使一些过程在结束时没有效果 跑步,虽然仍有工作要做。
何时不使用所有核心?根据我在R中运行日常cronjobs的个人经验中的一个例子,数据在RAM中相当于100-200GB数据,其中运行多个核心来处理数据块,我确实发现在32个中运行可用内核比使用20-30个内核更快。一个主要原因是儿童进程的内存需求(在一定数量的子进程开始运行后,内存使用量增加,而且事情显着减慢)。