如何在R并行计算中使用Reduce()函数?

Dan*_*iel 1 parallel-processing reduce r

我想将Reduce代码运行到out166000个列表元素的列表中:

trialStep1_done <- Reduce(rbind, out1)
Run Code Online (Sandbox Code Playgroud)

但是,运行需要很长时间.我想知道我是否可以借助并行计算包运行此代码.

我知道有mclapply,mcMap但我没有看到任何类似的功能mcReduce在并行计算软件包.

有没有像一个功能mcReduce做可Reduce与R中并行完成我想要做的任务吗?

非常感谢@BrodieG和@zheYuan Li,你的答案非常有帮助.我认为以下代码示例可以更精确地表示我的问题:

df1 <- data.frame(a=letters, b=LETTERS, c=1:26 %>% as.character())
set.seed(123)
df2 <- data.frame(a=letters %>% sample(), b=LETTERS %>% sample(), c=1:26 %>% sample() %>% as.character())
set.seed(1234)
df3 <- data.frame(a=letters %>% sample(), b=LETTERS %>% sample(), c=1:26 %>% sample() %>% as.character())
out1 <- list(df1, df2, df3)

# I don't know how to rbind() the list elements only using matrix()
# I have to use lapply() and Reduce() or do.call()
out2 <- lapply(out1, function(x) matrix(unlist(x), ncol = length(x), byrow = F))

Reduce(rbind, out2)
do.call(rbind, out2)
# One thing is sure is that `do.call()` is super faster than `Reduce()`, @BordieG's answer helps me understood why. 
Run Code Online (Sandbox Code Playgroud)

那么,此时,对于我的200000行数据集,do.call()可以很好地解决问题.

最后,我想知道这是否更快?或者@ZheYuanLi的演绎方式matrix()可能在这里?

Bro*_*ieG 7

问题不在于rbind,问题是Reduce.不幸的是,R中的函数调用很昂贵,尤其是当你不断创建新对象时.在这种情况下,您调用rbind65999次,每次执行时都会创建一个添加了一行的新R对象.相反,您可以rbind使用66000个参数调用一次,这将更快,因为内部rbind将在C中进行绑定,而无需调用R函数66000次并仅分配内存一次.在这里,我们将您的Reduce使用与Zheyuan的matrix/unlist 进行比较,最后使用rbindcalled with with do.call(do.call允许您调用一个具有指定为列表的所有参数的函数):

out1 <- replicate(1000, 1:20, simplify=FALSE)  # use 1000 elements for illustrative purposes

library(microbenchmark)    
microbenchmark(times=10,
  a <- do.call(rbind, out1),
  b <- matrix(unlist(out1), ncol=20, byrow=TRUE),
  c <- Reduce(rbind, out1)
)
# Unit: microseconds
#                                                expr        min         lq
#                           a <- do.call(rbind, out1)    469.873    479.815
#  b <- matrix(unlist(out1), ncol = 20, byrow = TRUE)    257.263    260.479
#                            c <- Reduce(rbind, out1) 110764.898 113976.376
all.equal(a, b, check.attributes=FALSE)
# [1] TRUE
all.equal(b, c, check.attributes=FALSE)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

哲源是最快的,但从各方面来看,这种do.call(rbind())方法非常相似.


李哲源*_*李哲源 5

  1. 它很慢,因为你反复打电话rbind.每次调用时,都必须在对象的维度增加时进行新的内存分配.
  2. 你的工作是受记忆限制的,你不会受益于并行性.在多核机器上,并行处理仅对CPU绑定任务有用.

如果我没有弄错你,你应该使用这个:

trialStep1_done <- matrix(unlist(out1), nrow = length(out1), byrow = TRUE)
Run Code Online (Sandbox Code Playgroud)

例:

out1 <- list(1:4, 11:14, 21:24, 31:34)

#> str(out1)
#List of 4
# $ : int [1:4] 1 2 3 4
# $ : int [1:4] 11 12 13 14
# $ : int [1:4] 21 22 23 24
# $ : int [1:4] 31 32 33 34

trialStep1_done <- matrix(unlist(out1), nrow = length(out1), byrow = TRUE)

#> trialStep1_done
#     [,1] [,2] [,3] [,4]
#[1,]    1    2    3    4
#[2,]   11   12   13   14
#[3,]   21   22   23   24
#[4,]   31   32   33   34
Run Code Online (Sandbox Code Playgroud)

感谢@ BrodieG的出色解释和基准测试结果!

我在笔记本电脑上尝试了基准测试,使用与@ BrodieG完全相同的代码,这就是我得到的:

Unit: microseconds
                                               expr      min       lq      mean
                          a <- do.call(rbind, out1)   653.60   670.36   900.120
 b <- matrix(unlist(out1), ncol = 20, byrow = TRUE)   170.16   177.60   224.036
                           c <- Reduce(rbind, out1) 65589.48 67519.32 72317.812
   median       uq       max neval
   745.54   832.36   2352.28    10
   183.98   286.84    385.96    10
 68897.36 69372.88 108135.96    10
Run Code Online (Sandbox Code Playgroud)