我是集群处理的新手,可以就如何更好地准备数据和/或从parallel包调用函数提出一些建议。我已经阅读了parallels包小插图,所以不清楚这是怎么回事。

我要并行化的函数调用2-D插值工具akima::interp。我的输入包含3个矩阵(或向量-在R中都相同):一个包含x坐标,一个包含y坐标,一个包含“z”或一组样本点的数据值。 interp使用它在常规网格上生成插值数据,因此我可以例如绘制字段。设置好这3个项目后,我将它们切成“块”,并将它们馈送到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

最佳答案

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

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

不幸的是,您无法确定unserialize花费了多少时间阻止,等待结果数据到达,以及它实际花费了多少时间来传输数据。结果可能很容易被工作人员计算出来,或者庞大,或者它们可能需要很长时间才能计算出来并且规模很小:无法从分析数据中看出来。

因此,为了使unserialize更快地执行,您需要使工作人员更快地计算其结果,或者尽可能减小结果。另外,使用makeCluster useXDR=FALSE选项可能会有所帮助。通过不使用XDR对数据进行编码,这可能会提高性能,从而使serializeunserialize都更快。

我认为将所有输入数据保存到.Rdata不会有任何帮助,因为您不需要花费很多时间将数据发送给工作人员,就象在serialize函数中花费的短时间所看到的那样。我怀疑这会使您放慢脚步。

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

关于r - 如何提高并行集群处理的速度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19380942/

10-11 04:30