如何提高并行集群处理的速度

时间:2013-10-15 12:13:05

标签: r parallel-processing cluster-computing

我是集群处理的新手,可以使用一些建议来了解如何更好地准备数据和/或从parallel包调用函数。我已经通过parallels包装小插图阅读了,所以对于发生了什么有一个模糊的想法。

我要并行化的函数调用2-D插值工具akima::interp。我的输入由3个矩阵(或向量 - R中的所有相同)组成:一个包含x坐标,一个包含y坐标,一个包含" z"或数据值,对于一组样本点。 interp使用它在常规网格上产生插值数据,因此我可以例如绘制字段。一旦我设置了这三个项目,我就把它们切成了#34; chunk"并将它们提供给clusterApply以按块执行interp块。

我使用的是Windows7,i7 CPU(8核)机器。这是Rprof的摘要输出,输入数据集为1e6点(如果您愿意,则为1000x1000),并映射到1000x1000输出网格。

所以我的问题是: 1)似乎"反序列化"占用大部分时间。这个操作是什么,怎么可以减少? 2)一般情况下,由于每个工作人员都加载了默认的.Rdata文件,如果我首先将所有输入数据保存到.Rdata,那么是否有任何速度增加,因此它不需要传递给工作人员? 3)其他任何我根本不知道我应该采用不同的方式吗?

注意:sin, atan2, cos, +, max, min功能发生在clusterApply来电之前。

Rgames> summaryRprof('bigprof.txt')
$by.self
                   self.time self.pct total.time total.pct
"unserialize"         329.04    99.11     329.04     99.11
"socketConnection"      1.74     0.52       1.74      0.52
"serialize"             0.96     0.29       0.96      0.29
"sin"                   0.06     0.02       0.06      0.02
"atan2"                 0.04     0.01       0.06      0.02
"cos"                   0.04     0.01       0.04      0.01
"+"                     0.02     0.01       0.02      0.01
"max"                   0.02     0.01       0.02      0.01
"min"                   0.02     0.01       0.02      0.01
"row"                   0.02     0.01       0.02      0.01
"writeLines"            0.02     0.01       0.02      0.01

$by.total
                     total.time total.pct self.time self.pct
"mcswirl"                331.98    100.00      0.00     0.00
"clusterApply"           330.00     99.40      0.00     0.00
"staticClusterApply"     330.00     99.40      0.00     0.00
"FUN"                    329.06     99.12      0.00     0.00
"unserialize"            329.04     99.11    329.04    99.11
"lapply"                 329.04     99.11      0.00     0.00
"recvData"               329.04     99.11      0.00     0.00
"recvData.SOCKnode"      329.04     99.11      0.00     0.00
"makeCluster"              1.76      0.53      0.00     0.00
"makePSOCKcluster"         1.76      0.53      0.00     0.00
"newPSOCKnode"             1.76      0.53      0.00     0.00
"socketConnection"         1.74      0.52      1.74     0.52
"serialize"                0.96      0.29      0.96     0.29
"postNode"                 0.96      0.29      0.00     0.00
"sendCall"                 0.96      0.29      0.00     0.00
"sendData"                 0.96      0.29      0.00     0.00
"sendData.SOCKnode"        0.96      0.29      0.00     0.00
"sin"                      0.06      0.02      0.06     0.02
"atan2"                    0.06      0.02      0.04     0.01
"cos"                      0.04      0.01      0.04     0.01
"+"                        0.02      0.01      0.02     0.01
"max"                      0.02      0.01      0.02     0.01
"min"                      0.02      0.01      0.02     0.01
"row"                      0.02      0.01      0.02     0.01
"writeLines"               0.02      0.01      0.02     0.01
"outer"                    0.02      0.01      0.00     0.00
"system"                   0.02      0.01      0.00     0.00

$sample.interval
[1] 0.02

$sampling.time
[1] 331.98

1 个答案:

答案 0 :(得分:9)

当调用clusterApply时,它首先向每个集群工作人员发送一个任务,然后等待每个人返回相应的结果。如果还有更多任务要做,它会重复该过程,直到完成所有任务。

它用于等待特定worker的结果的函数是recvResult,它最终调用unserialize从连接到该worker的套接字读取数据。因此,如果主进程大部分时间都在unserialize,那么它将花费大部分时间等待集群工作者返回任务结果,这是您希望在主服务器上看到的结果。如果它在serialize花费了大量时间,那就意味着它花了很多时间将任务发送给工人,这将是一个不好的迹象。

很遗憾,您无法确定unserialize花费多少时间阻止,等待结果数据到达,以及花费多长时间实际传输数据。结果可能很容易被工人计算得很大,或者他们可能需要很长时间来计算并且很小:没有办法从分析数据中分辨出来。

因此,为了使unserialize执行得更快,您需要让工作人员更快地计算结果,或者如果可能的话,将结果缩小。此外,使用makeCluster useXDR=FALSE选项可能会有所帮助。它可以通过不使用XDR对数据进行编码来提高性能,从而使serializeunserialize更快。

我不认为将所有输入数据保存到.Rdata会有所帮助,因为您没有花太多时间向工作人员发送数据,这可以从serialize中花费的时间很短看出来。功能。我怀疑这会让你慢下来。

我能想到的唯一其他建议是尝试使用parLapplyclusterApplyLB,而不是clusterApply。我建议使用parLapply,除非您有特定的理由使用其他功能之一,因为parLapply通常效率最高。当你的任务需要很长但可变的时间来执行时,clusterApplyLB非常有用。