9

我已经看到很多关于写入文件的问题,但我想知道打开文本文件、附加一些数据然后在要从多个连接写入时再次关闭它的最可靠方法是什么(即并行计算情况),并且不能保证每个连接何时要写入文件。

例如,在下面的玩具示例中,它仅使用我桌面上的内核,它似乎工作正常,但我想知道如果写入时间变长并且写入文件的进程数增加,这种方法是否容易失败(尤其是在可能存在一些延迟的网络共享上)。

当可能有其他从属进程想要同时写入文件时,任何人都可以提出一种可靠、明确的方式来打开、写入然后关闭连接吗?

require(doParallel)
require(doRNG)

ncores <- 7
cl <- makeCluster( ncores , outfile = "" )
registerDoParallel( cl )

res <- foreach( j = 1:100 , .verbose = TRUE , .inorder= FALSE ) %dorng%{
    d <- matrix( rnorm( 1e3 , j ) , nrow = 1 )
    conn <- file( "~/output.txt" , open = "a" )
    write.table( d , conn , append = TRUE , col.names = FALSE )
    close( conn )
}

我正在寻找最好的方法来做到这一点,或者是否有最好的方法。也许 R 并foreach自动处理我称之为 writelock 的问题?

谢谢。

4

3 回答 3

6

foreach 包不提供文件锁定机制,以防止多个工作人员同时写入同一个文件。这样做的结果将取决于您的操作系统和文件系统。当使用分布式文件系统(如 NFS)时,我会特别担心结果。

相反,我会更改您打开输出文件的方式以包含工作人员的进程 ID:

conn <- file( sprintf("~/output_%d.txt" , Sys.getpid()) , open = "a" )

如果需要,您可以在 foreach 循环返回后连接文件。

当然,如果您使用多台机器,您可能有两个具有相同进程 ID 的工作人员,因此您也可以在文件名中包含主机名Sys.info()[['nodename']],例如使用 .

于 2013-03-11T20:48:47.323 回答
4

@didierc 提出的方法的一种变体是从组合函数编写矩阵:

conn <- file("~/output.txt", "w")
wtab <- function(conn, d) {
    write.table(d, conn, col.names=FALSE)
    conn
}

res <- foreach(j = 1:100, .init=conn, .combine='wtab') %dorng% {
    matrix( rnorm( 1e3 , j ) , nrow = 1 )
}

close(conn)

当与 doSNOW 和 doMPI 等并行后端一起使用时,这种技术特别有用,它们可以在结果发送回主控时即时调用组合函数。

于 2013-03-11T22:18:35.193 回答
1

您也许可以尝试类似的方法:

res <- foreach( j = 1:100 , .verbose = TRUE , .inorder= FALSE ) %dorng%{
    matrix( rnorm( 1e3 , j ) , nrow = 1 )
}

conn <- file("~/output.txt", open = "a")
apply(res, 1, function (x, output) {
    write.table( x , conn , append = TRUE , col.names = FALSE )
  }, conn)

close(conn)

来源:数据框中的 foreach 行

于 2013-03-09T14:02:12.240 回答