是否在R中使用detectCores函数来指定并行处理的核心数?

Jer*_*lim 15 parallel-processing r

在它的帮助detectCores()说:

这不适合直接用于mclapply的mc.cores参数,也不适用于指定 makeCluster中的核心数.首先是因为它可能返回NA,其次是因为它没有给出允许的核心数.

但是,我已经看到了相当多的示例代码,如下所示:

library(parallel)
k <- 1000
m <- lapply(1:7, function(X) matrix(rnorm(k^2), nrow=k))

cl <- makeCluster(detectCores() - 1, type = "FORK")
test <- parLapply(cl, m, solve)
stopCluster(cl)
Run Code Online (Sandbox Code Playgroud)

where detectCores()用于指定其中的核心数makeCluster.

我的用例包括在我自己的多核笔记本电脑(OSX)上运行并行处理并在各种多核服务器(Linux)上运行它.因此,我不确定是否有更好的方法来指定内核数量,或者是否对于不使用的建议detectCores更多的是针对包含在广泛的硬件和操作系统环境中运行代码的开发人员.

总结如下:

  • 您是否应该使用detectCoresR中的函数来指定并行处理的核心数?
  • 检测到的和允许的核心之间的区别是什么?它们何时相关?

Ste*_*ton 15

我认为detectCores在调用mclapply或调用时作为工作人员/进程数量的起点是完全合理的makeCluster.但是,您可能需要或需要开始减少工作人员的原因有很多,甚至有些情况下您可以合理地开始更多工作.

例如,在一些超线程机器上设置它可能不是一个好主意mc.cores=detectCores().或者,如果您的脚本在HPC群集上运行,则不应使用比作业计划程序分配给您的作业更多的资源.您还必须在嵌套并行情况下小心,因为您的代码可能由调用函数并行执行,或者您并行执行多线程函数.一般来说,在开始长期工作之前运行一些初步基准来确定最佳工人数是个好主意.我通常监视基准测试,top以查看进程和线程的数量是否有意义,并验证内存使用是否合理.

您引用的建议特别适合包开发人员.这当然是一个坏主意一个包开发者总是启动detectCores()时调用的工人mclapply或者makeCluster,所以最好要离开的决定一直到最终用户.至少包应该允许用户指定要启动的工作者数量,但可以说detectCores()甚至不是一个好的默认值.这就是为什么包中包含mc.cores更改detectCores()getOptions("mc.cores", 2L)when 的默认值.mclapplyparallel

我认为你引用的警告的真正意义在于R函数不应该假设它们拥有整个机器,或者它们是脚本中使用多个核心的唯一函数.如果调用mclapplymc.cores=detectCores()在您提交给CRAN一个包,我希望在更改之前你的包将被拒绝.但是,如果您是最终用户,在您自己的计算机上运行并行脚本,则由您决定允许脚本使用多少个核心.

  • @Plinth在这种情况下,`detectCores()`没用多少.如果您使用批处理排队系统,通常可以使用环境变量来确定每个节点已分配给您的作业的核心数.在Torque上,您可以使用诸如`table(readLines(Sys.getenv('PBS_NODEFILE')))`之类的东西来计算$ PBS_NODEFILE中列出的节点名称.但通常,您可能必须将此信息指定为R脚本的命令行参数. (2认同)

Hen*_*ikB 7

未来软件包的作者:该future::availableCores()函数确认各种HPC环境变量(例如NSLOTSPBS_NUM_PPNSLURM_CPUS_PER_TASK)以及用于指定可用于该进程的内核数的系统和R设置,如果未指定,它将退回到parallel::detectCores()。当我或其他人意识到更多设置时,我很乐意为这些设置添加自动支持。在https://github.com/HenrikBengtsson/future/issues/22上有一个针对此问题的始终开放的GitHub问题(有一些公开的帮助请求)。

另外,如果sysadm在R_FUTURE_AVAILABLECORES_FALLBACK=1站点范围内设置环境变量,future::availableCores()则将返回1,除非通过其他方式(由作业计划程序,由用户设置等)明确覆盖。这样可以进一步防止默认情况下软件工具接管所有内核。

换句话说,如果您使用future::availableCores()而不是,parallel::detectCores()您可以确定自己的代码在多租户环境中运行良好(如果事实证明还不够,请在上述GitHub问题中告知我们),并且任何最终用户仍然可以无需更改代码即可控制内核数量。