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

Whether to use the detectCores function in R to specify the number of cores for parallel processing?

detectCores()help 中说:

This is not suitable for use directly for the mc.cores argument of mclapply nor specifying the number of cores in makeCluster. First because it may return NA, and second because it does not give the number of allowed cores.

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

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)

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

我的用例涉及在我自己的多核笔记本电脑 (OSX) 上 运行ning 并行处理和在各种多核服务器 (Linux) 上 运行ning 并行处理.所以,我不确定是否有更好的方法来指定核心数量,或者关于不使用 detectCores 的建议是否更适合包开发人员,因为代码意味着 运行硬件范围和 OS 环境。

总而言之:

我认为在调用mclapplymakeCluster时,以detectCores作为workers/processes数的起点是完全合理的。但是,您可能希望或需要启动更少的工人的原因有很多,甚至在某些情况下您可以合理地启动更多的工人。

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

您引用的建议特别适合包开发人员。对于包开发人员来说,在调用 mclapplymakeCluster 时始终启动 detectCores() worker 肯定是个坏主意,因此最好将决定权留给最终用户。至少这个包应该允许用户指定启动的工人数量,但可以说 detectCores() 甚至不是一个好的默认值。这就是当 mclapply 包含在 parallel 包中时 mc.cores 的默认值从 detectCores() 更改为 getOptions("mc.cores", 2L) 的原因。

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

在我的情况下(我使用 mac)更好的是 future::availableCores(),因为 detectCores() 显示 160,这显然是错误的。

parallelly package here: The parallelly::availableCores() function acknowledges various HPC environment variables (e.g. NSLOTS, PBS_NUM_PPN, and SLURM_CPUS_PER_TASK) and system and R settings that are used to specify the number of cores available to the process, and if not specified, it'll fall back to parallel::detectCores(). As I, or others, become aware of more settings, I'll be happy to add automatic support also for those; there is an always open GitHub issue for this over at https://github.com/HenrikBengtsson/parallelly/issues/17 的作者(有一些开放的帮助请求)。

此外,如果 sysadm 在站点范围内设置环境变量 R_PARALLELLY_AVAILABLECORES_FALLBACK=1,则 parallelly::availableCores() 将 return 1,除非通过其他方式明确覆盖(通过作业调度程序,通过用户设置,...)。这进一步防止软件工具默认接管所有内核。

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

编辑 2021-07-26:availableCores() 于 2020 年 10 月从 future to parallelly 移出。目前,出于向后兼容的原因,availableCores() 函数由 'future'包.