r - 与 R 并行置换矩阵列

标签 r for-loop matrix parallel-processing permutation

我正在尝试使用 R 按列置换矩阵。 然而,它需要很长时间(矩阵是 68k x 32k 整数)。

我想并行进行(因为每一列都是独立排列的)。我怎样才能实现它?应该是和 embarrassingly parallel for in R 有关系,但是没找到解决方法。

目前,我的功能如下:

permMTX <- function(x) {
    nr <- nrow(x)
    nc <- ncol(x)
    # I'd like to parallelize this for, since each
    # column can be permuted independently
    for (i in 1:nc) {
        x[,i] <- x[sample(nr),i]
    }
    x
} 

最佳答案

解决方案

首先,我会利用矢量化,这应该会提高效率。

permMTX = function(x) apply(x, 2L, sample)

然后我们可以使用库 parallel 来并行化该函数:

library(parallel)

parPermMTX = function(x, cluster) parApply(cl = cluster, X = x, MARGIN = 2L, FUN = sample)

用法

使用parallel,您必须在使用前注册一个集群。这是一个例子:

cl = makeCluster(detectCores(logical = FALSE))
parPermMTX(diag(10), cl)
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    0    1    0    0    0
#[2,]    0    0    0    0    0
#[3,]    0    0    0    0    0
#[4,]    1    0    0    1    1
#[5,]    0    0    1    0    0

parallel 的工作方式(产生多个 R 进程)你必须确保你有足够的内存来容纳你的数据的多个副本。

我认为也建议将数据导出到流程中,您只需调用即可做到这一点

clusterExport(cl, varlist = "exampleData")

虽然它确实在我这边并行运行,但它一点也不比简单地使用 apply 快,但我无法使用与你相同规模的数据进行测试,所以我不能确定它会起作用。

这是因为 sample 已经进行了高度优化,因此生成进程的开销比简单地调用 sample 更大。参见 Why is the parallel package slower than just using apply?

在我的系统上,对 68E3 个整数进行 32E3 次采样大约需要 40 秒:

microbenchmark(sample(68E3), times = 32E3)
#Unit: milliseconds
#          expr      min       lq     mean   median       uq      max neval
# sample(68000) 1.132273 1.192923 1.290838 1.227912 1.286229 7.880191 32000

也许你的内存不足,使用了硬盘缓存,这真的很慢。


第二个解决方案

那么,如果我们尝试将对 sample 的调用按顺序分配给单个进程会怎样?这是我在这里尝试的:

parPermMTX2 = function(x, cluster) do.call(cbind, parLapply(cl = cluster, X = list(x[,seq(floor(ncol(x)/2))], x[,floor(ncol(x)/2)+seq(ceiling(ncol(x)/2))]), fun = permMTX))

我们将x分成两半,然后分别调用permMTX,再与cbind重新组合。

遗憾的是,这两种方式都无法获得更好的性能。因此,虽然我回答了您的问题,但我不确定它是否有任何帮助。

关于r - 与 R 并行置换矩阵列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48832010/

相关文章:

r - 删除 R 中的行标识符

R: UseMethod 错误 ("tbl_vars")

r - 将图例添加到 r 中的 geom_line() 图中

r - dplyr:使用行而不是列进行变异

javascript - 如何移动到下一个 td 并检查 Css 类?

php - 在 PHP MYSQL 中选择框值

Matlab:如何动态更新for循环的限制?

C++ 矩阵 - 最小/最大元素

arrays - 遍历 3D 数组的算法复杂度

c - 打印出 double 矩阵