【问题标题】:How to parallelize for loops in R using multiple cores?如何使用多核并行化 R 中的循环?
【发布时间】:2022-01-05 13:49:47
【问题描述】:

我是 R 的初学者。我有一个任务,我需要执行类似于 for 循环的任务,但需要进行大量观察,在本例中为 500k 次。

for (number in 1:500000){
sqrt(number)}

问题是我需要对很多主题进行循环。 所以整个脚本看起来像这样:

for (subject in 1:400){
   for (number in 1:500000){
        sqrt(number)}
}

我想在我的多个核心 (16) 上并行化这个过程。 我发现在大多数教程中,他们会这样做:

library(foreach)
library(doParallel)
registerDoParallel(16)

然后他们继续使用以下方法简单地更改语法:

foreach (subject=1:400) %dopar% {
   for (number in 1:500000){
     sqrt(number)}
}

对我来说,将所有这些一起使用意味着我将在我的一个处理器上执行范围为 1:500000 的每个 for 循环。因此,这意味着,例如,如果我在 1:500000 循环中的一次迭代的时间复杂度为一小时,我将在一小时内进行 16 次迭代,因为我的每个处理器都会并行进行一次迭代。

在实践中,我通过跟踪经过时间的时间进行检查,似乎我的并行过程实际上比顺序过程慢得多。有什么我做错了吗?有没有一种简单的方法(对初学者友好)只告诉我的机器在我的机器的一个内核上并行执行每个 1:500000 迭代?

【问题讨论】:

    标签: r for-loop parallel-processing


    【解决方案1】:

    您没有做错任何事情,只是您正在运行的操作没有花费足够的时间来使并行执行变得经济。这是来自foreach vignette的sn-p:

    并行运行许多小任务通常比顺序运行需要更多的时间,如果它已经运行得很快,那么无论如何都没有动力让它运行得更快。但如果我们并行执行的操作需要一分钟或更长时间,就会开始有一些动力。

    如果我们运行 sqrt 不是 500,000 次,而是 50,000,000 次,您就会看到并行执行的好处。

    library(tictoc)
    library(foreach)
    library(doParallel)
    registerDoParallel(16)
    
    tic("no_parallel")
    
    for (subject in 1:400){
      for (number in 1:50000000){
        sqrt(number)}
    }
    
    toc()
    #> no_parallel: 271.312 sec elapsed
    
    tic("parallel")
    
    foreach (subject=1:400) %dopar% {
      for (number in 1:50000000){
        sqrt(number)}
    }
    
    toc()
    #> parallel: 65.654 sec elapsed
    

    【讨论】:

    • 请注意registerDoParallel(n) 使用不同的并行后端,具体取决于您是否在 MS Windows 上。具体来说,在 MS Windows 上,发生的情况是:cluster <- parallel::makeCluster(n),然后是registerDoParallel(cluster)。在 Linux 和 macOS 上,它使用 forked 并行进程,开销更少。我推荐使用 doParallel 的任何答案,应使用上述明确的形式以避免混淆和歧义。
    猜你喜欢
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2014-04-12
    • 2014-05-30
    • 1970-01-01
    相关资源
    最近更新 更多