从R脚本中将作业提交到从属节点?

时间:2012-10-30 15:55:28

标签: r parallel-processing hpc qsub torque

使用作业调度程序(具体为PBS)使myscript.R在群集从属节点上运行

目前,我使用以下命令将R脚本提交给从属节点

qsub -S /bin/bash -p -1 -cwd -pe mpich 1 -j y -o output.log ./myscript.R

R中是否有函数允许我在头节点上运行myscript.R并将各个任务发送到从节点?类似的东西:

foreach(i=c('file1.csv', 'file2.csv', pbsoptions = list()) %do% read.csv(i)

更新:qsub命令的替代解决方案是从#/usr/bin/Rscript的第一行删除myscript.R并直接调用它,如@Josh指出

qsub -S /usr/bin/Rscript -p -1 -cwd -pe mpich 1 -j y -o output.log myscript.R

4 个答案:

答案 0 :(得分:5)

如果您想从R脚本中提交作业,我建议您查看" BatchJobs"包。以下是DESCRIPTION文件的引用:

  

提供Map,Reduce和Filter变体,以便在PBS / Torque,LSF,SLURM和Sun Grid Engine等批处理计算系统上生成作业。

BatchJobs似乎比之前的类似软件包(如Rsge和Rlsf)更复杂。有注册,提交和检索作业结果的功能。这是一个简单的例子:

library(BatchJobs)
reg <- makeRegistry(id='test')
batchMap(reg, sqrt, x=1:10)
submitJobs(reg)
y <- loadResults(reg)

您需要配置BatchJobs以使用批处理排队系统。 submitJobs&#34;资源&#34;参数可用于为作业请求适当的资源。

如果您的群集不允许长时间运行的作业,或者严重限制长时间运行的作业数量,则此方法非常有用。 BatchJobs允许您通过将您的工作分解为多个作业来绕过这些限制,同时隐藏与手动执行相关的大部分工作。

the project website提供了文档和示例。

答案 1 :(得分:4)

对于我们的大部分工作,我们使用qsub(而不是)并行运行多个R会话。

如果是我常用的多个文件:

while read infile rest
do
qsub -v infile=$infile call_r.sh 
done < list_of_infiles.txt

call_r.sh:

...
R --vanilla -f analyse_file.R $infile
...

analyse_file.R:

args <- commandArgs()
infile=args[5]
outfile=paste(infile,".out",sep="")...

然后我将所有输出结合起来......

答案 2 :(得分:2)

R包Rsge允许将作业提交到SGE托管集群。它基本上将所需的环境保存到磁盘,构建作业提交脚本,通过qsub执行它们,然后整理结果并将它们返回给您。

因为它基本上包含了对qsub的调用,所以它也应该与PBS一起工作(虽然因为我不知道PBS,我不能保证它)。您可以通过更改Rsge关联的全局选项(options()输出中的前缀sge。)来更改qsub命令和使用的选项

它不再是CRAN,但它可以从github获得:https://github.com/bodepd/Rsge,虽然它看起来不再像以前一样。

要使用它,请使用随软件包提供的一个apply类型函数:sge.apply,sge.parRapply,sge.parCapply,sge.parLapply和sge.parSapply,它们是apply,rapply,rapply的并行等价项(t (x),......),lapply和sapply。除了传递给非并行函数的标准参数外,还需要一些其他参数:

njobs:             Number of parallel jobs to use

global.savelist:   Character vector giving the names of variables
                   from  the global environment that should be imported.

function.savelist: Character vector giving the variables to save from
                   the local environment.

packages:          List of library packages to be loaded by each worker process
                   before computation is started.

两个savelist参数和packages参数基本上指定在执行代码之前应将哪些变量,函数和包加载到在集群机器上运行的R的新实例中。 X的不同组件(列表项或data.frame行/列)在njobs不同作业之间划分,并作为作业数组提交给SGE。每个节点启动一个R实例加载指定的变量,函数和包,执行代码,保存并将结果保存到tmp文件。控制R实例检查作业何时完成,从tmp文件加载数据并将结果连接在一起以获得最终结果。

例如,计算基因列表随机样本的统计量:

library(Rsge)
library(some.bioc.library)

gene.list <- read.delim(“gene.list.tsv”)

compute.sample <- function(gene.list) {
   gene.list.sample <- sample(1000, gene.list)
   statistic <- some.slow.bioc.function(gene.list.sample)
   return (statistic)

}

results <- sge.parSapply(1:10000, function(x) compute.sample,
                         njobs = 100,
                         global.savelist = c(“gene.list”),
                         function.savelist(“compute.sample”),
                         packages = c(“some.bioc.library”))

答案 3 :(得分:1)

如果您希望在头节点上使用脚本时将任务发送到从属节点,我相信您的选项如下:

  1. 预先分配所有从属节点及它们,并在不需要时保持待机状态(正如我在第一个答案中所建议的那样)。
  2. 在需要从属节点时启动新作业,并将其结果保存到磁盘。将主进程置于保持状态,直到从属完成其任务,然后组装其输出文件。
  3. 选项2绝对是可能的,但实施起来需要更长的时间(我实际上已经多次完成它)。 @ pallevillesen的回答很明显。

    原始答案,错误解释的问题

    我自己从未与PBS合作,但看起来你可以用它来提交MPI工作。您可能需要在执行R脚本之前加载MPI模块,并将这些行中的shell脚本发送到qsub

    #!/bin/bash
    #PBS -N my_job
    #PBS -l cput=10:00:00,ncpus=4,mem=2gb
    
    module load openmpi
    module load R
    R -f myscript.R
    

    然后,您应该可以使用doSNOW并行执行foraech循环。

    n.slaves <- 4
    
    library(doSNOW)
    cl <- makeMPIcluster(n.slaves)
    registerDoSNOW(cl)
    
    foreach(i=c('file1.csv', 'file2.csv'), pbsoptions = list()) %dopar% read.csv(i)