在并行模式下运行具有多个参数的R函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在并行模式下运行具有多个参数的R函数相关的知识,希望对你有一定的参考价值。
我有这个功能
function1 <- function(df1, df2, int1, int2, char1)
{
...
return(newDataFrame)
}
它有5个输入:前2个是数据帧,然后我有两个整数和一个字符串。该函数返回一个新的数据框。
到目前为止,我依次运行此函数8次:
newDataFrame1 <- function1(df1, df2, 1, 1, "someString")
newDataFrame2 <- function1(df1, df2, 2, 0, "someString")
newDataFrame3 <- function1(df1, df2, 3, 0, "someString")
newDataFrame4 <- function1(df1, df2, 4, 0, "someString")
newDataFrame5 <- function1(df1, df2, 5, 0, "someString")
newDataFrame6 <- function1(df1, df2, 6, 0, "someString")
newDataFrame7 <- function1(df1, df2, 7, 0, "someString")
newDataFrame8 <- function1(df1, df2, 8, 0, "someString")
最后我使用rbind()组合结果:
newDataFrameTot <- rbind(newDataFrame1, newDataFrame2, newDataFrame3, newDataFrame4, newDataFrame5, newDataFrame6, newDataFrame7, newDataFrame8)
我想使用库(并行)并行运行它,但我无法弄清楚如何使这项工作。我在尝试:
cluster <- makeCluster(detectCores())
result <- clusterApply(cluster,1:8,function1)
newDataFrameTot <- do.call(rbind,result)
但这不起作用,除非我的函数function1()只有一个参数,我从1循环到8.但这不是我的情况,因为我需要传递5个输入。我怎样才能并行完成这项工作?
要迭代多个变量,clusterMap
非常有用。由于您只是在int1
和int2
上进行迭代,因此您应该使用“MoreArgs”选项来指定您没有迭代的变量:
cluster <- makeCluster(detectCores())
clusterEvalQ(cluster, library(xts))
result <- clusterMap(cluster, function1, int1=1:8, int2=c(1, rep(0, 7)),
MoreArgs=list(df1=df1, df2=df2, char1="someString"))
df <- do.call('rbind', result)
特别是,如果df1
和df2
是数据框并且它们被指定为迭代变量而不是使用“MoreArgs”,那么clusterMap
将迭代这些数据帧的列而不是将整个数据帧传递给function1
,这不是你的意思想。
请注意,使用命名参数以便正确传递参数非常重要。
关于绩效的说明
如果df1
或df2
非常大,您可以通过将它们导出到集群工作者来获得更好的性能。这避免了在每个任务中发送它们,但需要包装函数。这也意味着您不再需要使用“MoreArgs”选项:
clusterExport(cluster, c('df1', 'df2', 'function1'))
wrapper <- function(int1, int2, char1) {
function1(df1, df2, int1, int2, char1)
}
result <- clusterMap(cluster, wrapper, 1:8, c(1, rep(0, 7)), "someString")
如果工作人员执行多项任务,这允许重复使用df1
和df2
,但如果任务数量等于工作人员数量则没有意义。
要传递一个变量,您必须像您尝试的那样使用lapply
或sapply
的并行版本。但是,要传递许多变量,必须使用mapply
或Map
的并行版本。这将是clusterMap
,所以试试
clusterMap(cluster, function1, df1, df2, 1:8, c(1, rep(0, 7)), "someString")
编辑正如评论中指出的那样,这将引发错误。通常,长度为1的参数(例如本例中的"someString"
)应该循环到其他参数的长度(例如本例中的1:8
)。抛出的错误是由于数据帧不以相同的方式回收,而是被视为列表,因此它们的列重复而不是整个数据帧。这就是为什么你得到错误$ operator is invalid for atomic vectors
,因为在function1
内部,它试图在数据帧的提取列上使用$
,这是一个向量,而不是数据帧本身。这有两种补救措施。第一种是在MoreArgs
中传递其他参数,如另一个答案中所述。这需要你的参数被命名(无论如何这都是好的做法)。修复它的第二种方法是将每个数据框包装在一个列表中:
clusterMap(cluster, function1, list(df1), list(df2), 1:8, c(1, rep(0, 7)), "someString")
这将有效,因为现在整个数据框架df1
和df2
将被回收。可以看到差异,例如通过观察rep(df1, 2)
与rep(list(df1), 2)
的输出。
由于我最近在R中遇到了同样的问题,我附上了一个非常有用的网站的链接。这是一个新的multidplyr包,可以在R中进行并行处理。它绝对适用于Windows 10. :)
http://www.business-science.io/code-tools/2016/12/18/multidplyr.html
为了帮助您使用代码,这将是我建议的解决方案(没有测试,但应该像我在另一个例子中使用它一样工作)
#Install the packages
install.packages("devtools")
devtools::install_github("hadley/multidplyr")
require(multidplyr)
library(parallel)
cl <- detectCores()
cluster <- create_cluster(cores = cl)
cluster %>%
# Assign libraries
cluster_library("igraph") %>%
cluster_library("tidyverse") %>%
cluster_library("magrittr") %>%
cluster_library("dplyr") %>%
cluster_library("RColorBrewer") %>%
# Assign values (use this to load functions or data to each core)
cluster_assign_value("anyfunction", anyfunction)
result <- clusterMap(cluster, function1, int1=1:8, int2=c(1, rep(0, 7)),
MoreArgs=list(df1=df1, df2=df2, char1="someString"))
以上是关于在并行模式下运行具有多个参数的R函数的主要内容,如果未能解决你的问题,请参考以下文章