doParallel,集群与核心
Posted
技术标签:
【中文标题】doParallel,集群与核心【英文标题】:doParallel, cluster vs cores 【发布时间】:2015-05-03 22:57:18 【问题描述】:使用doParallel包时registerDoParallel
中的集群和核心有什么区别?
我的理解是否正确,在单机上这些是可以互换的,我会得到相同的结果:
cl <- makeCluster(4)
registerDoParallel(cl)
和
registerDoParallel(cores = 4)
我看到的唯一区别是 makeCluster()
必须使用 stopCluster()
显式停止。
【问题讨论】:
不确定,但我猜你会受到核心数量的物理限制,但不受集群数量的限制,即“并行运行并通过套接字通信的 R 副本的数量”。当然,集群可能共享同一个内核,具体取决于集群数/内核数的比率。 我倾向于同意@Pascal 的观点,除了实际尝试可以实现的目标和工作方式之外,单台机器上没有任何区别。如果你只是想并行化一些代码,那么这两种方式都没有关系。 【参考方案1】:我认为选择的答案过于笼统,实际上并不准确,因为它没有触及doParallel
包本身的细节。如果你读了这些小插曲,它实际上是很清楚的。
并行包本质上是多核的合并 包,由 Simon Urbanek 编写,还有雪包, 这是卢克蒂尔尼和其他人写的。多核 功能仅在那些操作的那些上支持多个工人 支持 fork 系统调用的系统;这不包括 Windows。经过 默认情况下,doParallel 在类 Unix 系统上使用多核功能 和 Windows 上的雪功能。
我们将在这个小插图中使用类似雪的功能,所以我们从 加载包并启动集群
要使用类似多核的功能,我们将指定 要使用的核心
总之,这取决于系统。集群是更通用的模式,覆盖所有平台,核心仅适用于类unix系统。
为使界面一致,包对这两种模式使用了相同的功能。
> library(doParallel)
> cl <- makeCluster(4)
> registerDoParallel(cl)
> getDoParName()
[1] "doParallelSNOW"
> registerDoParallel(cores=4)
> getDoParName()
[1] "doParallelMC"
【讨论】:
这应该被接受,因为它直接回答了OP的问题。【参考方案2】:是的,就在软件视图中。
在单机上这些是可以互换的,我会得到相同的结果。
为了清楚地理解“集群”和“核心”,我建议从“硬件”和“软件”层面思考。
在硬件级别,“集群”是指网络连接的机器,它们可以通过诸如套接字之类的通信一起工作(需要更多的初始化/停止操作,正如您所指出的stopCluster
)。而“核心”是指本地 CPU 中的多个硬件核心,它们通常通过共享内存一起工作(不需要从 A 显式发送消息到 B)。
在软件层面,有时cluster
和cores
的界限并不那么清晰。程序可以通过核心在本地运行,也可以通过集群远程运行,高级软件不需要知道细节。因此,我们可以混合使用两种模式,例如在本地使用显式通信作为在一台机器上设置cl
,
并且还可以在每台远程机器上运行多核。
回到你的问题,设置cl
或cores
是否相等?
从软件来看,程序由相同数量的客户端/服务器运行,然后得到相同的结果。
从硬件上来说,可能会有所不同。 cl
表示显式通信,cores
表示共享内存,但如果高级软件优化得很好。在本地机器中,这两个设置将进入相同的流程。我现在对doParallel
的研究不是很深,所以我不太确定这两个是否相同。
但实际上,最好为单机指定cores
,为集群指定cl
。
希望对你有所帮助。
【讨论】:
这太笼统了。 OP的问题是关于 doParallel 包的具体问题,而不是一般概念问题。对于这个问题,更多的是关于平台实现,即使是单机也不一样。【参考方案3】:doParallel::registerDoParallel(<numeric>)
的行为取决于操作系统,详情请参阅print(doParallel::registerDoParallel)
。
在 Windows 机器上,
doParallel::registerDoParallel(4)
有效
cl <- makeCluster(4)
doParallel::registerDoParallel(cl)
即它设置了四个(“PSOCK”)在后台 R 会话中运行的工作人员。然后,%dopar%
将基本上使用parallel::parLapply()
机器。使用这种设置,您必须担心全局变量和包会附加到每个工作人员上。
但是,在非 Windows 机器上,
doParallel::registerDoParallel(4)
结果将是%dopar%
将利用parallel::mclapply()
机制,而后者又依赖于分叉 进程。由于使用了分叉,因此您不必担心全局和包。
【讨论】:
要清楚,为什么doParallel::registerDoParallel(4)
在 unix-likes 上与 cl <- makeCluster(4, type = "FORK"); registerDoParallel(cl)
不一样?在我看来,这些应该是相同的,但在我的用例中后者要慢得多。
如果你遵循代码,你会看到doParallel::registerDoParallel()
在Unix 上最终会使用doParallel:::doParallelMC()
,它使用parallel::mclapply()
进行处理。相比之下,使用makeCluster(4, type = "FORK")
,或等效地,parallel::makeForkCluster()
设置了一个由分叉工作人员组成的 PSOCK 集群。当您将其传递给doParallel::registerDoParallel()
时,您最终将使用doParallel:::doParallelSNOW()
,它依赖于parallel::clusterApplyLB()
进行处理。所以,它是parallel::mclapply()
与 parallel::clusterApplyLB()
。以上是关于doParallel,集群与核心的主要内容,如果未能解决你的问题,请参考以下文章
使用并行或 doParallel 为多个操作系统作为 CRAN 包的自定义包