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

Car*_*oft 8 parallel-processing r cluster-computing

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

我要并行化的函数调用2-D插值工具akima::interp.我的输入由3个矩阵(或矢量 - 全部相同R)组成:一个包含x坐标,一个包含y坐标,一个包含一组采样点的"z"或数据值. interp使用它来在常规网格上产生插值数据,这样我就可以绘制字段.一旦我设置了这3个项目,我将它们切成"块"并将它们提供clusterApplyinterp大块执行块.

我正在使用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
Run Code Online (Sandbox Code Playgroud)

Ste*_*ton 9

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

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

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

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

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

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