在并行循环中添加CSV,没有错误

时间:2019-04-10 18:26:14

标签: r parallel-processing data.table

我需要使用并行循环附加CSV,我想知道是否有这样做但没有错误。

基本上,我需要处理大量数据,并且您无法将所有数据都放入内存,因此需要附加结果。这将永远需要lapply循环,因此我正在使用pbapply包。但是,在附加文件时,由于通常两个内核将同时附加,因此它弄乱了csv配置。

我假设有某种方法可以在某些集群正在处理文件时锁定与该文件的连接,而当关闭该连接以重试时,只有其他集群等待一会儿,但是我找不到办法去做。

这是我遇到的错误类型的一个示例:

library(parallel)
library(pbapply)
library(data.table)

write_random_thing <- function(x){
  require(data.table)

  y <- data.table(A = x, B = round(rnorm(10)*100,2))

  pth <- 'example.csv'
  fwrite(y, pth, append = TRUE)

  y
}

cl <- makeCluster(4)
xx <- pblapply(1:20, cl = cl, FUN = write_random_thing)
stopCluster(cl = cl)

yy <- rbindlist(xx)

zz <- fread('example.csv') # this will usually return an error

在这种情况下,yyzz应该相同(即使顺序不同),但是由于列数不是恒定的,所以甚至甚至无法读取文件。

我一直在寻找一些解决方案,如果尝试写文件时该文件被锁定,它会休眠几秒钟,然后重试。是否存在类似的东西?

2 个答案:

答案 0 :(得分:0)

我会做类似的事情来并行添加文件-

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( sprintf("~/output_%d.txt" , Sys.getpid()) , open = "a" )
    write.table( d , conn , append = TRUE , col.names = FALSE )
    close( conn )
}

答案 1 :(得分:0)

如果需要并行编写某些内容,则需要加锁以确保两个进程不会同时编写。

在R中使用软件包{flock}很容易做到这一点:

library(parallel)
library(pbapply)
library(data.table)

write_random_thing <- function(x){
  require(data.table)

  y <- data.table(A = x, B = round(rnorm(10)*100,2))

  pth <- 'example.csv'
  lock <- flock::lock(pth)
  fwrite(y, pth, append = TRUE)
  flock::unlock(lock)

  y
}

cl <- makeCluster(4)
xx <- pblapply(1:20, cl = cl, FUN = write_random_thing)
stopCluster(cl = cl)

yy <- rbindlist(xx)

zz <- fread('example.csv') # this will usually return an error