【问题标题】:Parallel processing and temporary files并行处理和临时文件
【发布时间】:2011-07-12 20:25:01
【问题描述】:

我正在使用multicore 包中的mclapply 函数进行并行处理。似乎所有启动的子进程都会为tempfile 函数给出的临时文件生成相同的名称。即,如果我有四个处理器,

library(multicore)
mclapply(1:4, function(x) tempfile())

将给出四个完全相同的文件名。显然我需要临时文件不同,以便子进程不会覆盖彼此的文件。当间接使用tempfile 时,即调用一些调用tempfile 的函数时,我无法控制文件名。

有没有办法解决这个问题? R 的其他并行处理包(例如foreach)是否有同样的问题?

更新:自 R 2.14.1 起,这不再是问题。

CHANGES IN R VERSION 2.14.0 patched:

[...]

o tempfile() on a Unix-alike now takes the process ID into account.
  This is needed with multicore (and as part of parallel) because
  the parent and all the children share a session temporary
  directory, and they can share the C random number stream used to
  produce the uniaue part.  Further, two children can call
  tempfile() simultaneously.

【问题讨论】:

    标签: r random parallel-processing multicore


    【解决方案1】:

    我相信multicore 会为每个子任务衍生出一个单独的进程。如果该假设是正确的,那么您应该能够使用Sys.getpid() 来“播种”临时文件:

    tempfile(pattern=paste("foo", Sys.getpid(), sep=""))
    

    【讨论】:

    • 如果我在自己的代码中调用 tempfile 这很好,但如果我调用 embedFonts,它会调用没有 PID 的 tempfile?
    • 好问题。 tempfile 调用tempdir,它会依次查询环境变量TMPDIRTMPTEMP。所以也许你可以Sys.setenv(TMPDIR=...)
    • 设置环境变量不起作用。 tempdir 似乎没有响应这些变化。我选择将您建议的代码猴子修补到tempfile - 我用该代码更新了原始问题。
    • 当前文档解释了为什么设置这些变量不起作用:“请注意,在 R 会话中设置任何这些环境变量对 tempdir() 没有影响:每个会话的临时目录是在之前创建的解释器已启动。”
    【解决方案2】:

    在你的函数中使用x

    mclapply(1:4, function(x) tempfile(pattern=paste("file",x,"-",sep=""))
    

    【讨论】:

      【解决方案3】:

      至少现在,我选择在我的.Rprofile 中使用以下代码来解决这个问题,按照 Daniel 的建议使用 PID 值。

      assignInNamespace("tempfile.orig", tempfile, ns="base")
      .tempfile = function(pattern="file", tmpdir=tempdir())
          tempfile.orig(paste(pattern, Sys.getpid(), sep=""), tmpdir)
      assignInNamespace("tempfile", .tempfile, ns="base")
      

      显然,对于您要分发的任何软件包,它都不是一个好的选择,但对于单个用户的需要,它是迄今为止最好的选择,因为它适用于所有情况。

      【讨论】:

      • 如果丹尼尔为你提供了答案,他不应该得到绿色的勾号吗?其他人怎么看?
      • 一种调和方法是将这个答案作为对原始 Q 的编辑,并将已解决的检查授予丹尼尔。我的两分钱。
      【解决方案4】:

      因为所有并行作业都同时运行,并且随机种子来自系统时间,所以并行运行四个临时文件实例通常会产生相同的结果(也就是说,如果您有 4 个内核。如果您只有两个核心,你会得到两对相同的临时文件名)。

      最好先生成临时文件名并将它们作为参数提供给您的函数:

      filenames <- tempfile( rep("file",4) )
      mclapply( filenames, function(x){})
      

      如果您使用的是其他人的函数,其中调用了 tempfile,那么如前所述,通过修改 tempfile 函数将 PID 处理到 tempfile 名称中,可能是最简单的计划:

      tempfile <- function( pattern = "file", tmpdir = tempdir(), fileext = ""){
         .Internal(tempfile(paste("pid", Sys.getpid(), pattern, sep=""), tmpdir, fileext))}
      mclapply( 1:4, function(x) tempfile() )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多