关于r:检测/确保在多核中使用多个内核

Detect/ensure use of multiple cores in multicore

我使用多核r包中的parallel和collect函数来并行化一个简单的矩阵乘法代码。答案是正确的,但并行版本似乎需要与串行版本相同的时间。

我怀疑它只在一个核心上运行(而不是在我的机器上有8个核心!).是否有方法检测此情况并确保使用1个以上的核心?

这是我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
library("multicore")

A = read.table("matrixA.txt")
B = read.table("matrixB.txt")
A = as.matrix(A)
B = as.matrix(B)
rows = dim(A)[1]
columns = dim(B)[2]

C <- mcparallel(A%*%B)
C <- collect(list(C))
C <- as.matrix(C[[1]])

write.table(C,"matrixC_mc.txt",row.names=FALSE, col.names=FALSE)


由于R 2.14.0包含的parallel包的detectCores()功能可以满足您查看是否有多个内核的需要:

1
2
3
R> parallel::detectCores()
[1] 8
R>

另外,mcparallel本身不会将矩阵乘法转换为并行操作(因为这是一个"困难"的问题,请参阅scalapack库)。但是你可以尝试一些简单的方法,比如:

1
2
3
4
5
6
7
8
R> X <- 1:1e3
R> rbenchmark::benchmark(serial=sapply(X, function(x) log(sqrt(x))),
+>                       parallel=mclapply(X, function(x) log(sqrt(x))),
+>                       replications=500)
      test replications elapsed relative user.self sys.self user.child sys.child
2 parallel          500  12.018    10.96     0.000    10.59      0.952     15.07
1   serial          500   1.097     1.00     1.208     0.00      0.000      0.00
R>

因此,对于500个简单操作(sqrt(log(x)))在短向量上的复制,并行增益。但生活从来就不是那么容易的:在更大的向量上,差异消失了:

1
2
3
4
5
6
7
8
R> X <- 1:1e5
R> rbenchmark::benchmark(serial=sapply(X, function(x) log(sqrt(x))),
+>                       parallel=mclapply(X, function(x) log(sqrt(x))),
+>                       replications=10)
      test replications elapsed relative user.self sys.self user.child sys.child
2 parallel           10   2.030     1.00     0.476    0.272      1.952     1.112
1   serial           10   2.821     1.39     2.228    0.592      0.000     0.000
R>

令人遗憾的是,并行计算很复杂,而且比将表达式插入mcparallelparallel要困难得多。


根据使用的操作系统,只需检查处理器的使用情况。当我使用并行处理时,我可以在top中清楚地看到我的六个处理器都被使用了。

对于您的代码示例,mcparallel(您不应该使用,根据手册使用parallel)只是用该表达式生成一个新的过程。所以,如果用矩阵乘法产生一个新的过程,只使用一个核心。只有在多次调用parallel时,才会启动多个进程,并使用多个核心。也许,如果您分割矩阵,在多个进程中运行它们,并在以后组合它们,您可以获得一些优势。你可以看看麦克拉普利。但是,并行线性代数可能更容易使用不使用multicore包,而是使用支持并行处理的blas版本。