为什么这段并行计算代码只用了1CPU?
Why is this parallel computing code only using 1 CPU?
我正在使用 foreach
和 parallel
库来执行并行计算,但由于某些原因,运行 一次只使用 1 个 CPU (我使用 'top'(Bash 在 Linux 终端上查找)。
服务器有48核,我试过了:
- 使用 24、12 或 5 核
- 示例代码(如下)
- 在 Windows 中,任务本身出现,但它们不使用任何 CPU
list.of.packages <- c("foreach", "doParallel")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if (length(new.packages)) install.packages(new.packages)
library(foreach)
library(doParallel)
no_cores <- detectCores() / 2 # 24 cores
cl<-makeCluster(no_cores)
registerDoParallel(cl)
df.a = data.frame(str = cbind(paste('name',seq(1:60000))), int = rnorm(60000))
df.b = data.frame(str = sample(df.a[, 1]))
df.b$int = NA
foreach(row.a = 1:length(df.a$str),
.combine = rbind,
.verbose = T) %dopar% {
row.b = grep(pattern = df.a$str[row.a], x = df.b$str)
df.b$int[row.b] = df.a$int[row.a]
df.b
}
stopCluster(cl)
我希望这段代码使用几个 CPU(定义的那么多),但它实际上使用了 1.
运行 foreach(..., verbose = TRUE)
了解发生了什么。稍微更改了 运行 的代码,以便在并行代码为 运行.
时更好地识别
library(foreach)
library(doParallel)
no_cores <- detectCores() / 2 # 24 cores
cl<-makeCluster(no_cores)
registerDoParallel(cl)
base = 2
out <- foreach(exponent = 2:400,
.combine = sum, .verbose = TRUE) %dopar%
runif(1000000)
第一段:
# discovered package(s):
# no variables are automatically exported
# explicitly exporting package(s):
# numValues: 3999, numResults: 0, stopped: TRUE
此设置不是并行的 - 这是您的主人设置您的 children。对于 2:40000000
,这需要很长时间,这可能是您停止的地方,并且您只会看到一个核心在使用中。
# numValues: 79, numResults: 0, stopped: TRUE
# got results for task n
您在等待打印时的计算应该是并行的。在 Windows 上,我看到 4 个核心正在计算每个 runif
。
# calling combine function
# evaluating call object to combine results:
# fun(accum, result.n)
这对每个具有不同 n 值的工人运行。这是你的组合函数,也不是并行的。
我认为您的代码在设置部分挂了,您只观察了操作的串行部分。如果没有,我会观察 verbose = TRUE
的情况并寻找更多线索。
我不知道您的主要问题是如何设置的,但是您的示例并不是如何设置并行化的好示例 - 您正在使用数百万工作人员来执行非常小的任务,因此您的串行开销成本为工人很高。如果您可以将更大的块发送给每个工人,您将看到性能的提高。
我正在使用 foreach
和 parallel
库来执行并行计算,但由于某些原因,运行 一次只使用 1 个 CPU (我使用 'top'(Bash 在 Linux 终端上查找)。
服务器有48核,我试过了:
- 使用 24、12 或 5 核
- 示例代码(如下)
- 在 Windows 中,任务本身出现,但它们不使用任何 CPU
list.of.packages <- c("foreach", "doParallel")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if (length(new.packages)) install.packages(new.packages)
library(foreach)
library(doParallel)
no_cores <- detectCores() / 2 # 24 cores
cl<-makeCluster(no_cores)
registerDoParallel(cl)
df.a = data.frame(str = cbind(paste('name',seq(1:60000))), int = rnorm(60000))
df.b = data.frame(str = sample(df.a[, 1]))
df.b$int = NA
foreach(row.a = 1:length(df.a$str),
.combine = rbind,
.verbose = T) %dopar% {
row.b = grep(pattern = df.a$str[row.a], x = df.b$str)
df.b$int[row.b] = df.a$int[row.a]
df.b
}
stopCluster(cl)
我希望这段代码使用几个 CPU(定义的那么多),但它实际上使用了 1.
运行 foreach(..., verbose = TRUE)
了解发生了什么。稍微更改了 运行 的代码,以便在并行代码为 运行.
library(foreach)
library(doParallel)
no_cores <- detectCores() / 2 # 24 cores
cl<-makeCluster(no_cores)
registerDoParallel(cl)
base = 2
out <- foreach(exponent = 2:400,
.combine = sum, .verbose = TRUE) %dopar%
runif(1000000)
第一段:
# discovered package(s):
# no variables are automatically exported
# explicitly exporting package(s):
# numValues: 3999, numResults: 0, stopped: TRUE
此设置不是并行的 - 这是您的主人设置您的 children。对于 2:40000000
,这需要很长时间,这可能是您停止的地方,并且您只会看到一个核心在使用中。
# numValues: 79, numResults: 0, stopped: TRUE
# got results for task n
您在等待打印时的计算应该是并行的。在 Windows 上,我看到 4 个核心正在计算每个 runif
。
# calling combine function
# evaluating call object to combine results:
# fun(accum, result.n)
这对每个具有不同 n 值的工人运行。这是你的组合函数,也不是并行的。
我认为您的代码在设置部分挂了,您只观察了操作的串行部分。如果没有,我会观察 verbose = TRUE
的情况并寻找更多线索。
我不知道您的主要问题是如何设置的,但是您的示例并不是如何设置并行化的好示例 - 您正在使用数百万工作人员来执行非常小的任务,因此您的串行开销成本为工人很高。如果您可以将更大的块发送给每个工人,您将看到性能的提高。