2012-11-26 15 views
6

Czy możliwe jest iteracyjne przetwarzanie pojedynczego pliku tekstowego na jednej maszynie wielordzeniowej równolegle z R? W przypadku kontekstu plik tekstowy zawiera od 250 do 400 MB danych wyjściowych JSON.Czy linie odczytu mogą być wykonywane równolegle w ramach R

EDIT:

Oto niektóre przykłady kodu I zostały gry z. Ku mojemu zaskoczeniu przetwarzanie równoległe nie wygrało - tylko podstawowe lapply - ale może to być spowodowane błędem użytkownika z mojej strony. Ponadto podczas próby odczytu wielu dużych plików moja maszyna się zatarła.

## 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) 

Tutaj drugi kod próbki

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

Czy problem występuje podczas odczytu pliku JSON lub podczas analizowania pliku JSON? –

+0

Ani. Moja maszyna ostatecznie zawiesza się, gdy próbuję użyć prostej pętli for. Próbowałem uruchomić funkcję przeciwko każdemu wpisowi JSON, zapisywać oddzielne pliki rds do odczytu z powrotem itd. Z każdą opcją, jestem również świadomy użycia pamięci i próbuję zoptymalizować i wyczyścić, kiedy to możliwe. Niektóre pomysły były okropne, ale na koniec chciałbym wymyślić sposoby na "analizowanie" większych zbiorów danych za pomocą Base R, ignorując fakt, że obecnie istnieją lepsze rozwiązania. – Btibert3

+0

Powtarzalny przykład znacznie ułatwiłby nam przekazywanie opinii. –

Odpowiedz

7

Odpowiedź zależy od tego, co Problem w rzeczywistości polega na: równoległym odczytywaniu pliku lub równoległym przetwarzaniu pliku.

Czytanie równolegle

Mógłbyś podzielić plik JSON do wielu plików wejściowych i przeczytać je równolegle, na przykład używając plyr funkcje połączone z równoległym backend:

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

Rejestrowanie backend można pewnie zrobić za pomocą pakietu parallel który jest teraz zintegrowany bazowej R. Lub można użyć pakietu doSNOW patrz this post on my blog szczegóły.

tworzenie równolegle

W tym scenariuszu najlepiej jest, aby przeczytać cały zestaw danych do wektora znaków, podzielić dane, a następnie użyć równoległego backend połączeniu z np funkcje plyr.

+1

Niezły pomysł. A jeśli szukasz sposobu na wyodrębnienie pliku, spójrz na komendę UNIX 'split'. –

+0

Polecenia Linuksa zawsze są dobrym rozwiązaniem;) –

+0

@JeffAllen Interesujące.Nie myślałem o wstępnym przetwarzaniu danych z wyprzedzeniem za pomocą poleceń. Nie jest ekspertem od linii poleceń, ale im bardziej się kręcę, widzę, jak potężne może być kilka poleceń. – Btibert3

2

readLines() prawdopodobnie nie z uwagi na charakter nierównoległe systemu plików IO. Oczywiście, jeśli używasz równoległego NFS lub czegoś w rodzaju HDFS, to ograniczenie nie będzie miało zastosowania. Ale zakładając, że jesteś w "standardowej" architekturze, nie będzie możliwe zrównoleglenie twoich połączeń readLine().

Najprościej byłoby prawdopodobnie przeczytać w całości akt skoro < 500MB prawdopodobnie będzie zmieścić się w pamięci, a następnie parallelize przetwarzanie raz jesteś obiekt jest już czytać.

+0

+1, ale przy odrobinie pracy prawdopodobnie można uzyskać równoległe "readLines", przypisując numery linii każdemu pracownikowi, który należy odczytać z danego połączenia pliku. –

+0

@PaulHiemstra czy możesz podać przykład tego, jak można to zrobić w najprostszym możliwym przypadku? :) –

+0

@AnthonyDamico Nie mam teraz czasu, ale myślę, że to nie jest trywialne i bardzo dobrze może nie działać. –

Powiązane problemy