我一直在使用这段代码:
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大约几秒钟,我猜这是结合结果。据system.time()
,用户时间为 14 秒,因此匹配。
现在我在 EC2 上运行,这是一个 36 核 c4.8xlarge,我看到它几乎所有时间都花在一个 100% 的核心上。更准确地说:有一个大约 10-20 秒的爆发,所有核心都在使用,然后大约 90 秒只有一个核心在 100%(被 R 使用),然后大约 45 秒的其他东西(我保存结果和加载下一批数据)。我正在批量处理 40,000 行、800 列。
根据顶部,长期平均负载徘徊在 5.00 附近。
这看起来合理吗?或者是否存在 R 并行性在通信开销上花费更多时间的点,我应该限制为例如 16 个内核。这里有什么经验法则吗?
参考:CPU 规格 我使用的是“Linux 4.4.5-15.26.amzn1.x86_64 (amd64)”。R 版本 3.2.2 (2015-08-14)
更新:我尝试了 16 个内核。对于最小的数据,运行时间从 13.9 秒增加到 18.3 秒。对于中型数据:
With 16 cores:
user system elapsed
30.424 0.580 60.034
With 35 cores:
user system elapsed
30.220 0.604 54.395
即开销部分花费了相同的时间,但并行位的内核更少,因此花费的时间更长,因此总体上花费的时间更长。
正如评论中所建议的那样,我也尝试过使用mclapply()
。它似乎确实要快一些(在我尝试过的特定测试数据上,类似于 330s 与 360s),但那是在我的笔记本电脑上,其他过程或过热可能会影响结果。所以,我还没有就此得出任何结论。