问题描述
我在学习使用 foreach
包时遇到了一些问题。目标是拥有一个利用并行性的可调用用户定义函数(最终将是一个自动脚本)。
简而言之,如果我不在用户定义的函数中放置 foreach
部分,则一切正常,但是当我这样做并调用该函数时,它会运行,但实际上并没有完成任何事情。
例如,所有这些都将保存到一个脚本中,然后根据需要获取和调用该脚本。
list('names' = c('a','b','c') -> test.list # just making up some dataframes
for(names in test.list[['names']]{
assign(paste0('dt.',name),data.frame('a' = 1:5)) # typically these dataframes would be
parallel::makeCluster(parallel::detectCores() - 1) -> cl # retrieved from an API
doParallel::registerDoParallel(cl)
foreach(name = test.list$name,.errorhandling = 'remove') %dopar%
save_file(name,path = desktop@location)
}
doParallel::stopImplicitCluster()
}
save_file <- function(name,path){
write.csv(get(paste0('df.',path = paste0(path,'/df.',name,'.csv'))
}
这就是要点:有几个文件需要从 API 中检索,但每个文件都需要一些时间。所以我想并行化他们的检索以保存到磁盘上。
如果我像这样运行脚本,它就可以工作。但是如果我写一个像这样的脚本:
automatic_get <- function(){
list('names' = c('a','c') -> test.list # just making up some dataframes
for(names in test.list[['names']]{
assign(paste0('dt.',data.frame('a' = 1:5)) # typically these dataframes would be
parallel::makeCluster(parallel::detectCores() - 1) -> cl # retrieved from an API
doParallel::registerDoParallel(cl)
foreach(name = test.list$name,.export = c('save_file'),# add the export for function
.errorhandling = 'remove') %dopar%
save_file(name,path = desktop@location)
}
doParallel::stopImplicitCluster()
}
}
save_file <- function(name,path){
write.csv(get(paste0('df.','.csv'))
# normally there wouldn't need to be get component to this; the file would be retrieved
# from within this function and then saved within this function
}
然后调用 automatic_get()
进程会运行,但实际上并没有运行。没有错误或任何提示,但没有文件被放置到磁盘上。
应该注意的是,调用的实际脚本是一个使用 reticulate
的 python 脚本,但同样,如果我不将所有内容都放在用户定义的函数中,它也可以工作。
任何帮助将不胜感激!
编辑:
我做的一个快速黑客是删除用户定义的函数部分,保存脚本。然后在另一个脚本(此处的脚本接收)中获取该特定脚本(带有 foreach 循环的脚本)。调用新创建的函数,该函数使用 foreach 获取脚本,而无需将 foreach 嵌套在用户定义的函数中,从而解决了该问题。但看起来,hacky?我还不得不重新安排脚本:
list('names' = c('a',data.frame('a' = 1:5)) # typically these
# dataframes would be retrieved via API
save_file <- function(name,'.csv'))
}
# The parallel part had to be placed at the bottom of the script
parallel::makeCluster(parallel::detectCores() - 1) -> cl # retrieved from an API
doParallel::registerDoParallel(cl)
foreach(name = test.list$name,path = desktop@location)
}
doParallel::stopImplicitCluster()
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)