当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


R mgcv.parallel mgcv 中的并行计算。


R语言 mgcv.parallel 位于 mgcv 包(package)。

说明

mgcv 可以利用多核或集群。

bam 可以使用基于 openMP 的并行化方法以及协变量的离散化来实现显著的加速。这是使用 bamdiscrete=TRUE 选项来选择的,线程数通过 nthreads 参数控制。这是扩展性最好的方法。请参阅下面的示例。

或者,函数 bam 可以使用 parallel 包中提供的函数。请参阅下面的示例。请注意,大多数多核机器的内存带宽有限,因此并行速度往往相当不稳定。

函数 gam 可以通过 openMP 在(共享内存)多核机器上使用并行线程(如果支持)。为此,请通过在 gamcontrol 参数中将 nthreads 设置为要使用的核心数来设置所需的线程数。请注意,在大多数情况下,只有主要的 步骤是并行的(n 是数据数量,p 是参数数量)。对于 GCV 估计的加性高斯模型,速度可能会令人失望,因为这些模型采用 SVD 步骤,这在实践中也可能产生大量成本。 magic 也可以使用多个核心,但相同的注释适用于 GCV 高斯加性模型。

NCVgam 一起使用时,通过在 gam.control 中设置 ncv.threads 可以获得值得的性能改进。

如果control$nthreads 设置为大于检测到的核心数,则仅使用检测到的核心数。请注意,使用虚拟核心通常只会带来很小的加速,甚至可能会稍微减慢计算速度。例如,许多报告有 4 个核心的英特尔处理器实际上有 2 个物理核心,每个核心有 2 个虚拟核心,因此使用 2 个线程可以显著提高速度,而使用 4 个线程几乎没有什么额外的区别。

请注意,在 Intel 和类似处理器上,通常通过在 BIOS 中禁用 Hyper-Threading,然后将线程数设置为所使用的物理核心数来实现最大性能。这可以防止操作系统调度程序将 2 个浮点密集型线程发送到同一物理核心,它们必须共享浮点单元(和缓存),从而相互减慢速度。调度程序倾向于在 mgcv 中使用的管理器-工作程序多线程方法下执行此操作,因为管理器线程在工作程序设置为工作的点之前看起来非常繁忙,并且在调度程序时,调度程序没有办法知道管理器线程实际上没有什么可做的,直到工作人员完成为止。如果您在无法禁用hyper-threading的多核平台上工作,那么可能值得将线程数设置为比物理核心数少一,以减少此类调度问题的频率。

mgcv 的工作分割始终做出简单的假设,即所有内核都是平等的,并且您不与其他浮点密集型线程共享它们。

除了 hyper-threading 之外,还有几个函数可能会导致缩放效果明显不佳。首先,许多CPU都有Turbo模式,只要CPU使用的总功率不超过设计限制,少数核心就可以以更高的频率运行,但是CPU上的所有核心都不可能以更高的频率运行。这个频率。因此,当您最终添加线程时,CPU 频率必须降低到 Turbo 频率以下,结果是您无法通过添加内核获得预期的速度。其次,大多数现代 CPU 都会根据负载动态设置频率。您可能需要设置系统电源管理策略以支持高性能,以便最大限度地提高所有线程以您希望的速度运行的机会(您可以在 BIOS 中关闭动态电源控制,但随后您也可以关闭涡轮也)。

由于 mgcv 中的计算负担全部在线性代数中,因此并行计算可能会通过调整的 BLAS 提供减少的好处或没有好处。如果您使用多线程 BLAS,情况尤其如此,但如果线程必须共享缓存,则经过调整以有效利用特定缓存大小的 BLAS 也可能会遇到性能损失。

例子

## illustration of multi-threading with gam...

require(mgcv);set.seed(9)
dat <- gamSim(1,n=2000,dist="poisson",scale=.1)
k <- 12;bs <- "cr";ctrl <- list(nthreads=2)

system.time(b1<-gam(y~s(x0,bs=bs)+s(x1,bs=bs)+s(x2,bs=bs,k=k)
            ,family=poisson,data=dat,method="REML"))[3]

system.time(b2<-gam(y~s(x0,bs=bs)+s(x1,bs=bs)+s(x2,bs=bs,k=k),
            family=poisson,data=dat,method="REML",control=ctrl))[3]

## Poisson example on a cluster with 'bam'. 
## Note that there is some overhead in initializing the 
## computation on the cluster, associated with loading 
## the Matrix package on each node. Sample sizes are low
## here to keep example quick -- for such a small model
## little or no advantage is likely to be seen.
k <- 13;set.seed(9)
dat <- gamSim(1,n=6000,dist="poisson",scale=.1)

require(parallel)  
nc <- 2   ## cluster size, set for example portability
if (detectCores()>1) { ## no point otherwise
  cl <- makeCluster(nc) 
  ## could also use makeForkCluster, but read warnings first!
} else cl <- NULL
  
system.time(b3 <- bam(y ~ s(x0,bs=bs,k=7)+s(x1,bs=bs,k=7)+s(x2,bs=bs,k=k)
            ,data=dat,family=poisson(),chunk.size=5000,cluster=cl))

fv <- predict(b3,cluster=cl) ## parallel prediction

if (!is.null(cl)) stopCluster(cl)
b3

## Alternative, better scaling example, using the discrete option with bam...

system.time(b4 <- bam(y ~ s(x0,bs=bs,k=7)+s(x1,bs=bs,k=7)+s(x2,bs=bs,k=k)
            ,data=dat,family=poisson(),discrete=TRUE,nthreads=2))

作者

Simon Wood <simon.wood@r-project.org>

参考

https://hpc-tutorials.llnl.gov/openmp/

相关用法


注:本文由纯净天空筛选整理自R-devel大神的英文原创作品 Parallel computation in mgcv.。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。