为什么doParallel R在这种情况下表现更差?

时间:2015-12-25 22:31:37

标签: r parallel-processing

有人可以解释为什么parLapply是最慢的吗?

> cl <- makeCluster(no_cores)
> myVar<-2:4000
> microbenchmark(
+ Reduce("+",parLapply(cl,myVar,function(X) X^2)),
+ Reduce("+",lapply(myVar,function(X) X^2)),
+ Reduce("+",myVar^2)
+ )
Unit: milliseconds
                                               expr      min       lq     mean   median       uq       max neval
 Reduce("+", parLapply(cl, myVar, function(X) X^2)) 6.988662 8.041860 9.061966 8.901447 9.916621 14.541828   100
        Reduce("+", lapply(myVar, function(X) X^2)) 5.256892 5.626853 6.892995 6.259239 8.165724 11.112812   100
                               Reduce("+", myVar^2) 1.930513 2.137887 2.613923 2.279481 3.000740  6.194623   100

根据评论,我添加了总和实现和矢量化实现:

> vec_exp<-Vectorize(function(x)x^2)
> cl <- makeCluster(no_cores)
> myVar<-2:4000
> microbenchmark(
+ Reduce("+",parLapply(cl,myVar,function(X) X^2)),
+ Reduce("+",lapply(myVar,function(X) X^2)),
+ Reduce("+",myVar^2),
+ sum(myVar^2),
+ Reduce("+",vec_exp(myVar))
+ )
Unit: microseconds
                                               expr      min       lq       mean   median       uq       max neval
 Reduce("+", parLapply(cl, myVar, function(X) X^2)) 6880.426 7086.400 7589.02901 7253.886 7625.246 12055.674   100
        Reduce("+", lapply(myVar, function(X) X^2)) 5073.078 5356.030 5826.33276 5478.029 5728.324  8472.236   100
                               Reduce("+", myVar^2) 1922.582 1998.861 2174.07136 2041.548 2129.023  4427.864   100
                                       sum(myVar^2)   13.530   17.495   19.65554   18.662   20.528    34.990   100
                        Reduce("+", vec_exp(myVar)) 5686.102 5967.655 6632.46879 6210.952 6671.186 16191.488   100

1 个答案:

答案 0 :(得分:4)

对于更多处理器Amdahls law开始启动。但是对于您的情况,设置并行系统的延迟(即使没有核心?不应该是1)在您的问题中起着重要作用。

生成集群通常需要很长时间,无论大小如何,这使得简单计算的并行效率降低。如果可能的话,vectorise通常会更好,并充分利用底层硬件。

此外,对并行lapply函数的调用要求它设置所有消息传递例程,拆分数据(在您的情况下为1),并准备好在计算后接收它。这表示您遇到的延迟。

另一方面,连续lapply只是开始计算,而不是担心上述任何一个。由于计算非常简单,因此它很快就会完成很多。 (即,不需要用parLapply设置的任何设置来处理。)

我建议比较一个2+核心并行场景。在这里你应该看到,对于简单/快速计算,最好保持程序串行,而对于更复杂的程序,它有助于分配工作(如果可能)。