我使用多核R包中的并行和收集函数来并行化简单的矩阵乘法代码。答案是正确的,但并行版本似乎与串行版本的时间相同。
我怀疑它只在一个核心上运行(而不是我机器上的8个核心!)。有没有办法检测到这种情况并确保使用超过1个核心?
这是我的代码:
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)
答案 0 :(得分:5)
自R 2.14.0以来所包含的detectCores()
软件包的parallel
功能可以实现您实际拥有多个内核所需的功能:
R> parallel::detectCores()
[1] 8
R>
此外,mcparallel
本身并不会将矩阵乘法转换为并行操作(因为这是一个“硬”问题,请参阅ScaLAPACK库)。但是你可以尝试一些简单的东西:
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>
因此,对于短向量,并行增益的简单操作(sqrt(log(x))
)的500次复制。但生活从未如此简单:在较大的载体上,差异消失了:
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>
令人遗憾的是,并行计算很棘手,而且比将表达式粘贴到mcparallel
或parallel
要困难得多。
答案 1 :(得分:4)
根据您使用的操作系统,只需检查您的处理器使用情况。当我使用并行处理时,我可以在top
中清楚地看到我的所有六个处理器都被使用了。
关于您的代码示例,mcparallel
(您不应该使用,根据手册使用parallel
)只会使用该表达式生成一个新进程。因此,如果使用矩阵乘法生成一个新进程,则只使用一个核心。仅在多次调用parallel
时,才会启动多个进程,并使用多个核心。也许如果你切割你的矩阵,在多个过程中运行它们,并在以后组合它们,你可以获得一些优势。你可以看看mclapply。但是并行线性代数可能更容易使用multicore
包,而是使用支持并行处理的blas
(线性代数库)版本。