Параллельная обработка и временные файлы - PullRequest
5 голосов
/ 10 марта 2011

Я использую функцию mclapply в пакете multicore для параллельной обработки.Кажется, что все запущенные дочерние процессы выдают одинаковые имена для временных файлов, заданных функцией 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.

Ответы [ 4 ]

7 голосов
/ 10 марта 2011

Я полагаю, multicore запускает отдельный процесс для каждой подзадачи.Если это предположение верно, то вы можете использовать Sys.getpid() для "заполнения" временного файла:

tempfile(pattern=paste("foo", Sys.getpid(), sep=""))
1 голос
/ 09 ноября 2011

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

Лучше сначала сгенерировать имена временных файлов и передать их своей функции в качестве аргумента:

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

Если вы используете чужую функцию, в которой есть вызов временного файла, то добавление PID в имя временного файла путем изменения функции временного файла, как было предложено ранее, является, вероятно, самым простым планом:

tempfile <- function( pattern = "file", tmpdir = tempdir(), fileext = ""){
   .Internal(tempfile(paste("pid", Sys.getpid(), pattern, sep=""), tmpdir, fileext))}
mclapply( 1:4, function(x) tempfile() )
1 голос
/ 10 марта 2011

Используйте x в своей функции:

mclapply(1:4, function(x) tempfile(pattern=paste("file",x,"-",sep=""))
0 голосов
/ 18 мая 2011

По крайней мере, на данный момент, я решил обойти все это, используя следующий код в моем .Rprofile, следуя совету Дэниела, чтобы использовать значения 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")

Очевидно, что это не очень хороший вариант для любого распространяемого вами пакета, но для одного пользователя это пока лучший вариант, поскольку он работает во всех случаях.

...