2012-11-26 43 views
6

是否可以在單個多核機器上與R並行迭代單個文本文件?對於上下文,文本文件在250-400MB的JSON輸出之間。可以在R中並行執行讀取線路

編輯:

這是我一直在玩的一些代碼示例。令我驚訝的是,並行處理沒有贏 - 只是基本的樂句 - 但這可能是由於我的用戶錯誤。另外,當試圖讀取一些大文件時,我的機器窒息。

## test on first 100 rows of 1 twitter file 
library(rjson) 
library(parallel) 
library(foreach) 
library(plyr) 
N = 100 
library(rbenchmark) 
mc.cores <- detectCores() 
benchmark(lapply(readLines(FILE, n=N, warn=FALSE), fromJSON), 
      llply(readLines(FILE, n=N, warn=FALSE), fromJSON), 
      mclapply(readLines(FILE, n=N, warn=FALSE), fromJSON), 
      mclapply(readLines(FILE, n=N, warn=FALSE), fromJSON, 
        mc.cores=mc.cores), 
      foreach(x=readLines(FILE, n=N, warn=FALSE)) %do% fromJSON(x), 
      replications=100) 

這裏是一個第二個代碼示例

parseData <- function(x) { 
    x <- tryCatch(fromJSON(x), 
       error=function(e) return(list()) 
       ) 
    ## need to do a test to see if valid data, if so ,save out the files 
    if (!is.null(x$id_str)) { 
    x$created_at <- strptime(x$created_at,"%a %b %e %H:%M:%S %z %Y") 
    fname <- paste("rdata/", 
        format(x$created_at, "%m"), 
        format(x$created_at, "%d"), 
        format(x$created_at, "%Y"), 
        "_", 
        x$id_str, 
        sep="") 
    saveRDS(x, fname) 
    rm(x, fname) 
    gc(verbose=FALSE) 
    } 
} 

t3 <- system.time(lapply(readLines(FILES[1], n=-1, warn=FALSE), parseData)) 
+0

閱讀JSON文件或解析JSON文件時出現問題嗎? –

+0

都沒有。當我嘗試使用簡單的for循環時,我的機器最終凍結。我試圖針對每個JSON條目運行一個函數,保存單獨的rds文件以讀回,等等。對於每個選項,我都會意識到內存使用情況並嘗試在可能的情況下進行優化和清理。有些想法很糟糕,但最後我想找出一些方法來「分析」更大的數據集,只是使用Base R,而忽略了目前存在更好的解決方案這一事實。 – Btibert3

+0

一個可重複的例子會讓我們更容易提供反饋。 –

回答

7

答案取決於什麼問題實際上是:並行讀取文件或並行處理文件。

並行

讀你可以在JSON文件分割成多個輸入文件以及並行讀取它們,例如使用plyr功能與並行後端結合:

result = ldply(list.files(pattern = ".json"), readJSON, .parallel = TRUE) 

註冊一個後端大概可以使用parallel包裏面已經集成在底座R.完成,或者您可以使用doSNOW包,見this post on my blog瞭解詳情。

處理並行

在這種情況下最好的辦法是讀取整個數據集成字符的向量,分割數據,然後使用一個並行後端與例如結合plyr功能。

+1

不是一個壞主意。如果您正在尋找一種方法來截斷文件,請查看UNIX的'split'命令。 –

+0

Linux命令總是一個很好的解決方案;) –

+0

@JeffAllen有趣。沒有真正想到用命令提前處理數據。在任何時候都不是命令行方面的專家,但是我越來越多地看到,我看到一些命令可能有多強大。 – Btibert3

2

可能不與readLines()由於非平行文件系統IO的性質。當然,如果你使用的是並行NFS或類似HDFS的東西,那麼這個限制就不適用了。但假設您使用的是「標準」體系結構,並行化您的readLine()調用將不可行。

您最好的選擇很可能是在整個文件中看到,因爲< 500MB讀取可能會適合在內存中,然後一旦你的對象是已經閱讀並行處理。

+0

+1,但通過一些工作,您可以通過爲每個需要從給定文件連接讀取的工作人員分配行號來獲得並行的'readLines'。 –

+0

@PaulHiemstra你能舉出一個最簡單的例子嗎? :) –

+0

@AnthonyDamico我現在沒有時間,但我認爲這不是微不足道的,它可能無法正常工作。 –