我使用R在具有多个节点和多个核心的群集上并行调用外部程序。外部程序需要三个输入数据文件并生成一个输出文件(所有文件都存储在同一个子文件夹中)。
要并行运行程序(或者更确切地说是以并行方式调用它),我最初将foreach
函数与doParallel
库一起使用。只要我在一个节点上使用多个核心,这种方法就可以正常工作。
但是,我想使用具有多个核心的多个节点。因此,我相应地修改了我的代码,以便将doSNOW
库与foreach
结合使用(我尝试了Rmpi
和doMPI
,但我没有设法在多个节点上运行代码与那些图书馆)。
这工作正常,我。即外部程序现在确实在多个节点(具有多个核心)上运行,并且群集日志文件显示它产生所需的结果。但是,我现在面临的问题是,外部程序不再将结果/输出文件存储在主节点上/工作目录的指定子文件夹中(当我使用{{1 }})。这使我无法将结果导入R。
实际上,如果我检查相关文件夹的内容,它不包含任何输出文件,尽管日志文件清楚地显示外部程序成功运行。我猜它们存储在不同的节点上(?)。
我需要对doParallel
函数或我设置群集的方式进行哪些修改,以便将这些文件保存在主节点/工作目录中指定子文件夹中?
这里有一些示例R代码,用于展示我正在做的事情:
foreach
我的群集的pbs脚本如下所示:
# #Set working directory in non-interactive mode
setwd(system("pwd", intern = T))
# #Load some libraries
library(foreach)
library(parallel)
library(doParallel)
# ####Parallel tasks####
# #Create doSNOW cluster for parallel tasks
library(doSNOW)
nCoresPerNode <- as.numeric(Sys.getenv("PBS_NUM_PPN"))
nodeNames <- system("cat $PBS_NODEFILE | uniq", intern=TRUE)
machines <- rep(nodeNames, each = nCoresPerNode)
cl <- makeCluster(machines, type = "SOCK")
registerDoSNOW(cl)
# #How many workers are we using?
getDoParWorkers()
#####DUMMY CODE#####
# #The following 3 lines of code are just dummy code:
# #The idea is to create input files for the external program "myprogram"
external_Command_Script.cmd # #command file necessary for external program "myprogram" to run
startdata # #some input data for "myprogram"
enddata # #additional input data for "myprogram"
####DUMMY CODE######
# #Write necessary command and data files for external program: THIS WORKS!
for(i in 1:100)){
write(external_Command_Script.cmd[[i]], file=paste("./mysubfolder/external_Command_Script.",i,".cmd", sep=""))
write.table(startdata, file=paste("./mysubfolder/","startdata.",i,".txt", sep=""), col.names = FALSE, quote=FALSE)
write.table(enddata, file=paste("./mysubfolder/","enddata.",i,".txt", sep=""), col.names = FALSE, quote=FALSE)
}
# #Run external program "myprogram" in parallel: THIS WORKS!
foreach(i = 1:100)) %dopar% {
system(paste('(cd ./mysubfolder && ',"myprogram",' ' ,"enddata.",i,".txt ", "startdata.",i,".txt", sep="",' < external_Command_Script.',i,'.cmd)'))
}
# #Import results of external program: THIS DOES NOT WORK WHEN RUN ON MULTIPLE NODES!
results <- list()
for(i in 1:100)){
results[[i]] = read.table(paste("./mysubfolder/","enddata.txt.",i,".log.txt", sep=""), sep = "\t", quote="\"", header = TRUE)
}
# #The import does NOT work as the files created by the external program are NOT stored on the master node/in the
# #subfolder of the working directory!
# #Instead I get the following error message:
# #sh: line 0: cd: ./mysubfolder: No such file or directory
# #Error in { : task 6 failed - "cannot open the connection"
答案 0 :(得分:1)
我建议您查看batchtools包。它提供了与来自R的TORQUE / PBS相互作用的方法。
如果您可以暂时使用它的前任BatchJobs,我也建议尝试一下,当您了解其工作方式时,请查看doFuture foreach适配器。这将允许您使用future.BatchJobs包。 doFuture,future.BatchJobs和BatchJobs的这种组合允许您从R内部执行所有操作,并且您不必担心创建临时R脚本等。(免责声明:我是两者的作者)。< / p>
示例在您设置它之后它会是什么样子:
## Tell foreach to use futures
library("doFuture")
registerDoFuture()
## Tell futures to use TORQUE / PBS with help from BatchJobs
library("future.BatchJobs")
plan(batchjobs_torque)
然后你使用:
res <- foreach(i = 1:100) %dopar% {
my_function(pathname[i], arg1, arg2)
}
这将评估单独PBS作业中的每次迭代,即您将看到添加到队列中的100个作业。
future.BatchJobs的插图有更多的例子和信息。
更新2017-07-30:future.batchtools套餐自2017年5月起在CRAN上发布。现在推荐使用此软件包,以供将来使用.BatchJobs。用法与上述非常相似,例如:现在使用plan(batchjobs_torque)
代替plan(batchtools_torque)
。
答案 1 :(得分:0)
问题解决了:
我犯了一个错误:外部程序实际上没有运行 - 我误解了日志文件。外部程序未运行的原因是找不到子文件夹(包含必要的输入数据)。似乎群集默认为用户目录,而不是pbs提交脚本中指定的工作目录。此行为与使用Gemfile
创建的集群不同,后者确实可以识别工作目录。因此,只需在R脚本中添加工作目录和子文件夹的相对路径即可解决问题。即gem install
而非doParallel
。或者,您也可以使用该文件夹的完整路径。