Каков наиболее надежный способ добавления текста в один файл из нескольких подключений

Я видел много вопросов относительно записи в файл, но мне интересно, что больше всего надежный способ открыть текстовый файл, добавить некоторые данные и затем закрыть его снова, когда вы собираетесь писать со многих подключений (т.е. в параллельной вычислительной ситуации) и не можете гарантировать, когда каждое соединение захочет записать в файл,

Например, в следующем примере игрушек, который использует только ядра на моем рабочем столе, кажется, что он работает нормально, но мне интересно, будет ли этот метод подвержен неудаче, если записи будут длиннее и количество процессов, записывающих файл увеличивается (особенно через общий сетевой ресурс, где может быть некоторое время ожидания).

Может ли кто-нибудь предложить надежный, окончательный способ открытия соединений, записи и последующего закрытия, когда могут быть другие подчиненные процессы, которые хотят писать в файл одновременно?

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 позаботились о том, что я могу назвать автоматическими проблемами в журнале?

Спасибо.

+7
источник поделиться
3 ответа

Пакет foreach не обеспечивает механизм блокировки файлов, который предотвращает одновременное запись нескольких сотрудников в один и тот же файл. Результат этого будет зависеть от вашей операционной системы и файловой системы. Меня особенно беспокоят результаты при использовании распределенной файловой системы, такой как NFS.

Вместо этого я бы изменил способ открытия выходного файла, чтобы включить идентификатор процесса рабочего:

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

Вы можете объединить файлы после возврата цикла foreach, если хотите.

Конечно, если вы использовали несколько машин, у вас могут быть два сотрудника с одинаковым идентификатором процесса, поэтому вы можете также включить имя хоста в имени файла, например, используя Sys.info()[['nodename']].

+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, которые могут вызывать функцию комманды "на лету", поскольку результаты отправляются обратно ведущему устройству.

+4
источник

Вместо этого вы можете попробовать что-то вроде этого:

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 в фрейме данных

+1
источник

Посмотрите другие вопросы по меткам или Задайте вопрос