【问题标题】:Using R Parallel with other R packages将 R Parallel 与其他 R 包一起使用
【发布时间】:2015-05-04 18:56:12
【问题描述】:

我正在使用 R 中的 LQMM 包进行非常耗时的分析。我将模型设置为在星期四开始运行,现在是星期一,并且仍在运行。我对模型本身充满信心(作为标准 MLM 测试),并且我对我的 LQMM 代码充满信心(已经使用相同的数据集运行了其他几个非常相似的 LQMM,并且它们都花了一天的时间来运行)。但我真的很想弄清楚如何使用我可以访问的机器的并行处理能力(注意所有机器都是基于 Microsoft Windows),如果可能的话,让它运行得更快。

我已经阅读了几篇关于使用并行的教程,但我还没有找到一个展示如何将并行包与其他 R 包一起使用的教程……我是在想这个,还是不可能?

这是我使用 R 包 LQMM 运行的代码:

install.packages("lqmm")
library(lqmm)
g1.lqmm<-lqmm(y~x+IEP+pm+sd+IEPZ+IEP*x+IEP*pm+IEP*sd+IEP*IEPZ+x*pm+x*sd+x*IEPZ,random=~1+x+IEP+pm+sd+IEPZ, group=peers, tau=c(.1,.2,.3,.4,.5,.6,.7,.8,.9),na.action=na.omit,data=g1data)

数据集包含 58 个变量的 122433 个观测值。所有变量均采用 z 评分或虚拟编码。

【问题讨论】:

  • 如果没有看到您的代码或数据,实际上不可能说出问题所在。
  • 已编辑以包含代码和有关数据的一些信息。让我知道这是否足够,或者是否需要更多信息。

标签: r parallel-processing multicore


【解决方案1】:

需要在所有节点上评估依赖库。为此,parallel 包中预见到了函数 clusterEvalQ。您可能还需要将一些数据导出到子节点的全局环境:为此,您可以使用clusterExport 函数。另请查看this page,了解有关可能对您有用的其他相关功能的更多信息。

一般来说,为了通过使用多个内核来加速您的应用程序,您必须将您的问题分解为多个子部分,这些子部分可以在不同的内核上并行处理。要在 R 中实现这一点,您首先需要创建一个集群并为其分配特定数量的核心。接下来,您必须注册集群,将所需的变量导出到节点,然后评估每个子节点上的必要库。您设置集群和启动节点的确切方式将取决于您将使用的子库和函数的类型。例如,当您选择使用 doParallel 包(以及大多数其他并行化子库/函数)时,您的集群设置可能如下所示:

library(doParallel)
nrCores <- detectCores()
cl <- makeCluster(nrCores)
registerDoParallel(cl); 
clusterExport(cl,c("g1data"),envir=environment());
clusterEvalQ(cl,library("lqmm"))

集群现已准备就绪。您现在可以将全局任务的子部分分配给集群中的每个单独节点。在下面的一般示例中,集群中的每个节点都将处理全局任务的子部分 i。在示例中,我们将使用 doParallel 包提供的 foreach %dopar% 功能:

doParallel 包为 foreach/%dopar% 函数使用 R 2.14.0 的并行包和 稍后。

子结果将自动添加到resultList。最后,当所有子流程都完成后,我们合并结果:

resultList <- foreach(i = 1:nrCores) %dopar%
{
   #process part i of your data.
}
stopCluster(cl)
#merge data..

由于您的问题不是专门针对如何拆分数据,我将让您自己弄清楚这部分的详细信息。但是,您可以在我对this post 的回答中找到使用doParallel 包的更详细示例。

【讨论】:

  • 谢谢!因此,如果不进行大量代码重写和/或数据拆分,就没有办法真正自动并行运行包。我想我得继续努力了!
【解决方案2】:

听起来您想使用并行计算来更快地执行lqmm 函数的单个调用。为此,您必须:

  • lqmm的一次调用拆分为多个函数调用;
  • lqmm 中并行化一个循环。

通过指定较小的迭代值,可以将某些函数拆分为多个较小的部分。示例包括在ntree 参数上并行化randomForest,或在nstart 参数上并行化kmeans。另一种常见的情况是将输入数据拆分成更小的块,并行地对这些块进行操作,然后组合结果。当输入数据是数据框或矩阵时,通常会这样做。

但是很多时候为了并行化一个函数,你必须修改它。它实际上可能更容易,因为您可能不必弄清楚如何分解问题并组合部分结果。您可能只需要将lapply 调用转换为并行lapply,或将for 循环转换为foreach 循环。但是,理解代码通常很耗时。分析代码也是一个好主意,以便您的并行化真正加快函数调用。

我建议您下载lqmm 包的源代码分发并开始阅读代码。尝试了解它的结构并了解哪些循环可以并行执行。如果幸运的话,您可能会想出一种方法将一个调用拆分为多个调用,否则您将不得不在您的机器上重新构建一个修改版本的包。

【讨论】:

  • 谢谢!因此,如果不进行大量代码重写和/或数据拆分,就没有办法真正自动并行运行包。我想我得继续努力了!