我是并行计算概念的新手
(我试图将其应用于一个脚本,其中一个循环构建几个回归模型大约1000次并且每次基于这些模型的系数进行预测。每种情况下的数据集太大而且模型涉及虚拟代码和权重,这进一步减慢了进程。因此,我试图应用foreach而不是'for'循环。)
我正在尝试使用doParallel
和foreach
库,并使用registerDoParallel()
设置核心数。我有一台Windows 10机器。我的理解是像detectCores()
和。{
Sys.getenv('NUMBER_OF_PROCESSORS')
将返回“逻辑处理器”而不是核心的数量:
> detectCores()
[1] 4
我的任务管理器显示这些规范
我试着尝试一下我应该用registerDoParallel()
设置的“正确”(?)内核数量,并意识到它会接受任何数字。我进行了一些实验,发现这甚至会产生影响。我已经从这两个libraries(第3页)的创建者那里调整了上面的脚本,以比较串行到并行执行与不同数量的内核。
x <- iris[which(iris[,5] != "setosa"), c(1,5)]
trials <- 10000
library(foreach)
library(doParallel)
#detectCores()
#Sys.getenv('NUMBER_OF_PROCESSORS')
registerDoParallel(cores = 4)
getDoParWorkers()
ptimes = numeric(15)
stimes = numeric(15)
for (i in 1:15) {
stime <- system.time({
r <- foreach(icount(trials), .combine=cbind) %do% {
ind <- sample(100, 100, replace=TRUE)
result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
coefficients(result1)
}
})[3]
stimes[i] = stime
}
for (i in 1:15) {
ptime <- system.time({
r <- foreach(icount(trials), .combine=cbind) %dopar% {
ind <- sample(100, 100, replace=TRUE)
result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
coefficients(result1)
}
})[3]
ptimes[i] = ptime
}
这是结果,以一次迭代的平均时间(秒)来衡量。它似乎在12“核心”有一个甜蜜点。
过程意味着sd
顺序:53.8 5.4
“双核”:32.3 1.9
“4核”:28.7 2.6
“12核”:22.9 0.5
“24核”:27.5 1.9
我甚至将“2核”和“12核”之间的平均性能与t检验进行了比较,并且它们并非偶然。
我的问题是:
基于上述原因,在使用可并行化的代码时,以“12核模式”运行脚本是不是很好?
我想使用性能更高的计算机来运行我的脚本;我是否需要重复此过程以找到最佳(=最快)的性能?
答案 0 :(得分:1)
在实践中,最好将相同数量的硬件(物理上,实例中为2个)设置为计算线程。
更多详情:
如果您的工作负载计算密集型,则更多线程(大于硬件核心)将竞争资源并降低性能。但是,在某些情况下,例如您的示例,工作负载每次计算需要大量内存访问,以便更多线程可以隐藏内存延迟。实际上,CPU是延迟方向,它可以自动隐藏延迟。在您的情况下,超过2个线程可以获得进一步的改进但不会太多。
因此,与每次运行时不同系统上的调整时间(应该使用多少线程?)相比,最好在并行计算程序中使用#cold内核。
在here中使用R进行并行计算的一个很好的介绍。