【问题标题】:Parallelization using shared memory [bigmemory]使用共享内存进行并行化 [bigmemory]
【发布时间】:2017-10-17 07:06:32
【问题描述】:

在尝试使其在并行场景 [doSNOW] 中工作时遇到了一些困难,其中涉及到共享内存 [bigmemory] ​​的使用。总结是我在某些 foreach 工作人员中收到以下错误“Error in { : task 1 failed - “cannot open the connection””。更具体地说,检查集群输出日志,它与“'/temp/x_bigmatrix.desc': Permission denied”有关,例如并发访问 big.matrix 描述符文件时出现问题.

请原谅,但由于代码有点复杂,我不包括可重现的示例,而是尝试用要点解释工作流程是什么。

我有一个矩阵X,通过:

转换成big.matrix
x_bigmatrix <- as.big.matrix(x_matrix, 
                             type = "double", 
                             separated = FALSE,
                             backingfile = "x_bigmatrix.bin",
                             descriptorfile = "x_bigmatrix.desc",
                             backingpath = "./temp/")

然后,我使用 doSNOW [我在 Windows 10 x64 上] 初始化 sock 集群:

cl <- parallel::makeCluster(N-1, outfile= "output.log")
registerDoSNOW(cl)

(showConnections() 正确显示已注册的连接)

现在我必须解释一下,我对每个工作人员都有一个主循环(foreach),然后有一个内部循环,每个工作人员在 X 中的行上循环。主要思想是,在主语料库中,每个工作人员通过内部循环顺序获取数据块,然后,每个工作人员可以存储其中一些观察结果,而不是自己存储观察结果;它们存储行索引以供后验检索。为了使事情变得更加复杂,每个工作人员都修改了存储索引的关联 R6 类环境。我这样说是因为对 big.matrix 描述符文件的访问发生在两个不同的地方:主 foreach 循环和每个 R6 环境中。 foreach主要语料库如下:

workersOutput <- foreach(worker = workers, .verbose = TRUE) %dopar% {
    # In the main foreach loop I don't include the .packages argument because 
    # I do source with all the needed libraries at the beginning of the loop
    source(libs)

    # I attach the big.matrix using attach.big.matrix and the descriptor file
    x_bigmatrix <- attach.big.matrix("./temp/x_bigmatrix.desc")

    # Now the inner for loop is going to loop over the rows in X.
    # Each worker can store some of these indices for posterior retrieval
    for (i in seq(1, nrow(X)) {
        # Each R6 object associated with each worker is modified, storing indices...
        # Within these environments, there is read-only access through a getter using the same
        # procedure that above: x_bigmatrix <- attach.big.matrix("./temp/x_bigmatrix.desc")
    }
}
stopCluster(cl)

当尝试访问文件中支持的 big.matrix 时,问题发生在内部循环中。因为如果我更改这些环境中的行为以显式存储观察结果而不是行索引(因此,无法再访问这些对象中的描述符文件),那么它可以正常工作。此外,如果我在没有并行化 [registerDoSEQ()] 的情况下运行它,但将行索引存储在对象中,也不会出现错误。因此,如果我在不同的 R6 环境中混合并行化和对共享 big.matrix 的双重访问,就会出现问题。奇怪的是,一些工人可以比其他工人运行更长的时间,甚至最后至少有一个完成它的运行......所以这让我想到了同时访问 big.matrix 描述符文件的问题.

我是否在一些基础知识方面失败了?

【问题讨论】:

  • 你确定bigmemory 可以这样并行化吗?我建议您与包维护者核实它是否设计为多个进程可以同时安全地访问同一个文件。让多个进程读取一个静态文件并没有那么复杂,但是如果文件有任何类型的更新(按用户或按包),那么事情就会变得复杂得多。
  • 显然应该,不是吗? stackoverflow.com/questions/31575585/… 在我的例子中,它没有在 R6 类和环境中添加所有这些东西......
  • 如果问题是对 big.matrix 描述符文件的并发访问,您不能只传递描述符对象(使用describe)而不是包含该对象的描述符文件吗?跨度>
  • 天哪,它的工作原理!我仍然不完全理解为什么使用描述符(来自描述函数)的附加过程有效,但使用完整的文件备份路径却没有。因为最终,底层行为是相同的,不是吗?但它的伎俩,谢谢! :)
  • @F.Privé 请将答案放在下面,以便 OP 可以接受答案并且可以关闭此问题。

标签: r r-bigmemory rparallel


【解决方案1】:

如果问题是对 big.matrix 描述符文件的并发访问,您可以只传递描述符对象(使用describe)而不是包含该对象的描述符文件。

说明: 从描述符文件附加时,它首先创建big.matrix.descriptor 对象,然后从该对象附加big.matrix。因此,如果您直接使用该对象,它将被复制到您的所有集群中,您可以从它们中附加big.matrix

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 2016-12-27
    • 2011-06-20
    • 2012-07-19
    • 2012-10-15
    • 2022-01-03
    相关资源
    最近更新 更多