2017-07-13 4 views
0

Ich habe Schwierigkeiten beim Parallelisieren von R für die Optimierung der Geschwindigkeit von Funktionsaufrufen beim Schreiben in eine Datei. Die Funktion ist einfach, aber die Dateien, die es erstellt, sind massiv und sie brauchen eine unangemessene Zeit. Ich habe Profvis verwendet, um zu visualisieren, wohin die Zeit geht, und es scheint, dass die Verdächtigen in der cat-Anweisung am Ende der Funktion und im Capture-Schritt beim Schreiben in die Ausgabedatei stehen. Ich habe unten ein vereinfachtes, kleines, reproduzierbares Beispiel-Skript eingefügt, aber die tatsächlichen Dateien sind sehr umfangreich und ich verwende sie auf einem Supercomputer-Cluster. Das parallele Ausführen des Skripts wie geschrieben gibt mir keine Geschwindigkeitssteigerung, aber ich weiß nicht, wie ich die foreach-Anweisung so strukturieren soll, dass sie jede Iteration der Funktion parallel erfasst. Wenn ich foreach in die Funktion selbst bringe, bekomme ich Probleme mit der Reihenfolge (anstelle von Header, Basisparese, Header, Basenpaaren etc. fügt sie zufällig hinzu - wie auch immer sie sich aus welchem ​​Kern auch immer herausgelöst haben) und setzen sie in die capture.output line, scheint eigentlich nichts zu tun.Verwenden von Foreach in einer Funktionsdefinition vs. Verwenden von Foreach zum Schreiben in eine Datei

Vorgesehen Ausgabe:

ACCTTCGAA 
1321:1007 
GGGTCAATA 
1258:1115 
GGGCCTACG 
1335:1642 
ATCATCGCC 
1547:1735 
TCTCAACGA 
1518:1935 
TTGTGTTCT 
1352:1828 
CCTTTCGGC 
1403:1162 
ACAATTCGC 

Reproduzierbare Beispielskript:

library(doParallel) 
library(foreach) 


#create cluster with desired number of cores 
cl <- makeCluster(20) 

# Register cluster 
registerDoParallel(cl) 

#create example data 
bps <- replicate(10,paste(sample(size = 30, x = c("A","C","G","T"), replace = TRUE), collapse = "")) 
true_false <- replicate(10,paste(sample(size = 1, x = c("T","F"), replace = TRUE), collapse = "")) 
my.df<- data.frame(bps, true_false) 


#create function to make unique Header 
    Header = function(){ 
    header = c(sample(1000:2000, 1), ":", sample(1000:2000, 1)) 
    paste(header, collapse="") 
    } 


#assemble reads: 
    make_file <- function(df) { 
    bps <- NULL 
    fragment <- seq(from=1, to=(nrow(df))) 
    first.9<- seq(from=1, to=9) 
    for(i in 1:nrow(df)){ 
     header <- Header() 
     fragment[i] <- df[i,1] 
     first.9 <- substring(fragment,1,9) 
     bps[i] <- cat(header, first.9[i], sep = "\n") 
    } 
    return(bps) 
    } 



    #regular capture 
capture.output(make_file(df = my.df), file = "myfile1.txt", append = TRUE) 

    #foreach capture 
foreach(x=(capture.output(make_file(df = my.df), file = "myfile2.txt", append = TRUE))) %dopar% {x} 
+0

Hallo @ user8173816 Wenn meine Antwort mit Ihrem Problem geholfen hat, können Sie es als Antwort akzeptieren, indem Sie auf das Häkchen auf der linken Seite klicken. Es teilt der Community mit, dass es funktioniert hat und dass Ihr Problem geschlossen wurde. – CPak

Antwort

0

foreach bereits bietet Verhalten Looping und versucht, den Ausgang zu montieren (die Sie angeben können).

Ihre Daten:

bps <- replicate(10,paste(sample(size = 30, x = c("A","C","G","T"), replace = TRUE), collapse = "")) 
true_false <- replicate(10,paste(sample(size = 1, x = c("T","F"), replace = TRUE), collapse = "")) 
my.df<- data.frame(bps, true_false) 

Neuer Code:

library(readr) 
library(iterators) 
library(foreach) 

newfile <- foreach(i=iter(my.df,by="row"), .combine="rbind") %do% { as.data.frame(rbind(Header(), substring(i$bps,1,9))) } 
write_tsv(newfile, "C:/temp/temp.txt", append=F, col_names=F) 

jeweils in loop von foreach durch my.df für Zeile durchlaufen. Dann %do% die folgenden: rbindHeader() und substring..., dann in data.frame. Schließlich .combine der Ausgang mit rbind. Dies erzeugt einen einzelnen Spalten-Datenrahmen. Schreiben Sie in die Ausgabedatei mit write_tsv....

Ausgang:

  V1 
1 1054:1658 
2 GACCACTCC 
3 1578:1988 
4 CAAACGGCT 
5 1604:1065 

------ parallelisieren --------

parallelisieren, einfach %do% mit %dopar% ersetzen. Abhängig davon, wie viele Einträge Sie haben, kann %do% tatsächlich schneller sein.

+0

Dank @Chi Pak, es dauerte eine Weile, bis ich mit der eigentlichen (viel komplexeren) Funktion arbeiten konnte, aber es scheint, als ob ich auf den kleinen Testsets herumlaufen würde tatsächliche Daten auf dem Cluster. – user8173816

+0

Bei Speicherproblemen können Sie entweder: A) jede Zeile sofort in eine Datei schreiben (also nicht zu einer großen R-Struktur zusammenfügen) oder B) Ihre Eingabedatei in kleine Stapel aufteilen. Sie müssen eine neue Frage stellen, wenn Sie spezifischere Hilfe benötigen. – CPak

Verwandte Themen