2012-11-26 19 views
6

E 'possibile iterativo su un singolo file di testo su una singola macchina multi-core in parallelo con R? Per il contesto, il file di testo è compreso tra 250 e 400 MB di output JSON.Può leggere linee in parallelo in R

EDIT:

Ecco alcuni esempi di codice che ho giocato in giro con. Con mia sorpresa, l'elaborazione parallela non ha vinto - solo lapply di base - ma ciò potrebbe essere dovuto a un errore dell'utente da parte mia. Inoltre, durante il tentativo di leggere un numero di file di grandi dimensioni, la mia macchina si è bloccata.

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

Ecco un secondo esempio di codice

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

Il problema è nella lettura del file JSON o nell'analisi del file JSON? –

+0

Né. La mia macchina alla fine si blocca quando provo a usare un ciclo for semplice. Ho tentato di eseguire una funzione su ogni voce JSON, salvare file rds separati per la lettura, ecc, ecc. Con ogni opzione, sono anche consapevole dell'utilizzo della memoria e cerco di ottimizzare e pulire quando possibile. Alcune idee erano orribili, ma alla fine, voglio capire come "analizzare" serie di dati più grandi solo con Base R, ignorando il fatto che esistono soluzioni migliori per il momento. – Btibert3

+0

Un esempio riproducibile renderebbe molto più facile per noi fornire un feedback. –

risposta

7

La risposta dipende da ciò che il il problema in realtà è: leggere il file in parallelo o elaborare il file in parallelo.

lettura in parallelo

Si potrebbe dividere il file JSON in più file di input e leggerli in parallelo, per esempio utilizzando le plyr funzioni combinate con un back-end in parallelo:

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

Registrazione di un backend probabilmente può essere fatto utilizzando il pacchetto parallel che è ora integrato nella base di R. oppure è possibile utilizzare il pacchetto doSNOW, vedere this post on my blog per i dettagli.

Elaborazione in parallelo

In questo scenario la soluzione migliore è di leggere l'intero insieme di dati in un vettore di caratteri, suddividere i dati e quindi utilizzare un backend parallelamente ad esempio in combinazione con le funzioni plyr.

+1

Non è una cattiva idea. E se stai cercando un modo per tagliare il file, dai un'occhiata al comando 'split' di UNIX. –

+0

I comandi di Linux sono sempre una buona soluzione;) –

+0

@JeffAllen Interessante.Non pensavo davvero di pre-elaborare i dati prima del tempo con i comandi. Non è un esperto alla linea di comando da nessuna parte, ma più mi aggiro, vedo quanto potenti possano essere alcuni comandi. – Btibert3

2

probabilmente non con readLines() a causa della natura di non-Parallel File-sistema IO. Naturalmente, se si utilizza un NFS parallelo o qualcosa come HDFS, questa restrizione non verrà applicata. Ma supponendo che tu sia su un'architettura "standard", non sarà possibile parallelizzare le tue chiamate readLine().

La cosa migliore sarebbe probabilmente quello di leggere l'intero file visto che < 500MB probabilmente rientrare nella memoria, quindi parallelizzare il trattamento una volta che sei oggetto è già letta.

+0

+1, ma con un po 'di lavoro si potrebbe probabilmente ottenere 'readLines' paralleli assegnando numeri di riga a ciascun lavoratore che devono leggere da una determinata connessione di file. –

+0

@PaulHiemstra puoi dare un esempio di come ciò potrebbe essere fatto nel caso più semplice possibile? :) –

+0

@AnthonyDamico Non ho tempo in questo momento, ma penso che non sia banale, e potrebbe benissimo non funzionare. –

Problemi correlati