2011-03-10 40 views
5

我使用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. 

回答

0

至少現在,我選擇了猴子 - 通過在丹尼爾的建議下使用我的.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") 

顯然它並不適合你分發任何包一個很好的選擇,但是對於單個用戶的需求是最好的選擇到目前爲止,因爲它適用於所有情況。

+0

如果丹尼爾提供了答案,他不應該得到綠色的標記嗎?其他人認爲什麼? – 2012-01-10 13:41:52

+0

一個協調的方法是將此答案作爲對原始Q的編輯,並將解答的檢查提供給Daniel我的兩分錢。 – 2012-01-10 14:21:20

7

我相信multicore爲每個子任務旋轉一個單獨的過程。如果這種假設是正確的,那麼你應該能夠使用Sys.getpid()爲「種子」臨時文件:

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

這是好的,如果我在我自己的代碼中調用臨時文件,但如果我打電話,說的embedFonts,該臨時文件通話,而PID? – otsaw 2011-03-11 08:41:01

+0

好問題。 'tempfile'調用'tempdir',按此順序查詢環境變量'TMPDIR','TMP'和'TEMP'。因此,也許你可以'Sys.setenv(TMPDIR = ...)' – 2011-03-11 15:25:27

+0

設置環境變量沒有工作。 'tempdir'似乎沒有迴應這些變化。我選擇將你的建議代碼修改爲'tempfile' - 我使用該代碼更新了原始問題。 – otsaw 2011-03-14 10:59:22

1

在功能使用x

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

因爲並行作業在同一時間全部程序,因爲隨機種子來自系統時間,運行臨時文件的四個實例並行通常會產生相同的結果(如果你有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())