Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
r%dopar%嵌套循环未并行运行_R_Nested Loops_Doparallel_Parallel Foreach - Fatal编程技术网

r%dopar%嵌套循环未并行运行

r%dopar%嵌套循环未并行运行,r,nested-loops,doparallel,parallel-foreach,R,Nested Loops,Doparallel,Parallel Foreach,我正在通过使用%dopar%运行一个嵌套循环,以生成用于体验目的的虚拟数据集。 参考链接: 样本数据集 问题 当我在%dopar%上运行时,我确实使用资源监视器来监视我的机器的CPU性能,我注意到CPU没有得到充分利用 问题: 我确实尝试在我的机器i5上运行上述脚本(test1和test2),4核。但是,似乎%do%和%dopar%的运行时间彼此接近。这是我的脚本设计问题?我的真实数据由50k唯一ID组成,这意味着如果在%do%中运行,将花费很长时间,我如何才能充分利用我的机器CPU来减少运行

我正在通过使用
%dopar%
运行一个嵌套循环,以生成用于体验目的的虚拟数据集。 参考链接:

样本数据集

问题 当我在
%dopar%
上运行时,我确实使用
资源监视器来监视我的机器的CPU性能,我注意到CPU没有得到充分利用

问题:
我确实尝试在我的机器i5上运行上述脚本(test1和test2),4核。但是,似乎
%do%
%dopar%
的运行时间彼此接近。这是我的脚本设计问题?我的真实数据由
50k
唯一ID组成,这意味着如果在
%do%
中运行,将花费很长时间,我如何才能充分利用我的机器CPU来减少运行时间?

我相信您已经看到了foreach包的初始开销,因为它复制并设置了正确运行每个循环所需的一切。在运行你的代码大约30-60秒后,我的cpu的利用率太高了,直到代码最终完成

也就是说,它不能解释为什么您的代码比
%do%
循环慢。我相信这里的罪魁祸首在于当您试图访问所有foreach循环中的数据时,foreach循环是如何应用的。基本上,如果您不这样做。导出您需要的数据,它将尝试在几个并行会话中访问相同的数据,并且每个会话将不得不等待,而其他会话将完成访问自己的数据。 使用foreach中的
.export
参数导出数据可能会缓解这一问题。就我个人而言,我使用其他软件包来执行我的大部分并行化,所以如果这是您想要的,我建议进行测试。然而,这将带来更大的开销

更快的方法: 现在,当您试图创建一个虚拟数据集时,对于该数据集,某些列的所有组合都被组合在一起,有一些更快的方法可以获得该数据集。快速搜索“交叉连接”将

对于data.table软件包,使用“CJ”功能可以非常高效和快速地完成。简单地

output <- CJ(ID, year, month)

输出相关:看起来所有CPU上都有运行的东西,这可能是Windows对每个CPU施加的限制吗?嗨@Oliver,谢谢你的评论!通过应用您的建议,CJ功能对我的交叉连接问题非常有效。您是对的,我遇到了开销问题,尤其是在运行并行处理时,涉及到
rbind
,很高兴您给出了导致开销问题的重要因素(缺少
.export
语句)。:)你好@Oliver,我可以知道你通常使用哪种parallization软件包吗?没问题,我很高兴能帮上忙。对于我自己的编程,我最经常使用并行包本身。许多问题可以用parApply或Parlappy解决(如果输出不是类似矩阵的)。然而,在任何情况下,如果问题可以分为几个块,并且并行化可以分为这些块,而不必迭代许多较小的问题,则可以获得很大的好处。每次迭代都会增加一点开销(在大多数情况下是很小的),因此让4个进程执行所有工作,而不是100个进程在较小的块中执行同样的工作会更好。对于使用
futures
(或
furr
)的非标准并行进程,
承诺
ipc
包可以帮助执行异步并行化,尽管它变得更加技术化,并且需要一些时间来研究这个问题。我相信foreach可以利用迭代器块状结构来执行大小等于或小于内核数的块计算,而不是通过一个小迭代器来执行。然而,我仍然要研究这个属性,这可能使foreach包在一些非标准情况下更快。
library(foreach)  
library(data.table)
library(doParallel)

# parallel processing setting
cl <- makeCluster(detectCores() - 1)
registerDoParallel(cl)
system.time(
  output_table <- foreach(i = seq_along(ID), .combine=rbind, .packages="data.table") %:%
    foreach(j = seq_along(year), .combine=rbind, .packages="data.table") %:%
    foreach(k = seq_along(month), .combine=rbind, .packages="data.table") %dopar% {

    data.table::data.table(
      mbr_code = ID[i],
      year = year[j],
      month = month[k]
    )
  }
)
stopCluster(cl)

#---------#
# runtime #
#---------#
>    user  system elapsed 
> 1043.31   66.83 1171.08
system.time(
  output_table <- foreach(i = seq_along(ID), .combine=rbind, .packages="data.table") %:%
    foreach(j = seq_along(year), .combine=rbind, .packages="data.table") %:%
    foreach(k = seq_along(month), .combine=rbind, .packages="data.table") %do% {

    data.table::data.table(
      mbr_code = ID[i],
      year = year[j],
      month = month[k]
    )
  }
)
stopCluster(cl)

#---------#
# runtime #
#---------#
> user  system elapsed 
> 1101.85    1.02 1110.55 
> view(output_table)
output <- CJ(ID, year, month)