2017-07-13 17 views
0

ファイルへの書き込み時に関数呼び出しの速度を最適化するためにRを並列化するのが難しいです。この関数は単純ですが、作成するファイルは大量であり、無理な時間がかかります。私はprofvisを使って、時間がどこにあるのかを視覚化しています。そして、関数の終わりにはcatステートメントに、出力ファイルにはキャプチャステップでは容疑者が表示されているようです。私は以下のシンプルで小さな、再現可能なサンプルスクリプトを含んでいますが、実際のファイルは膨大で、スーパーコンピューティングクラスタ上で実行しています。 scripを並列で実行してもスピードは向上しませんが、関数の各反復を実際に並列に取り込むようにforeach文をどのように構造化すればいいか分かりません。 foreachを関数自体に入れておくと、ヘッダー、ベースペア、ヘッダー、ベースペアなどの代わりに、それらをランダムに追加しますが、順序は問題になりますが、実行中のコアから外れてしまいました。 capture.output行は、実際に何もしていないようです。対象foreachを関数定義で使用するとforeachを使用してファイルに書き込む

出力:

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

再現スクリプトの例:

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

こんにちは@ user8173816私の回答が問題の解決に役立つ場合は、左側のチェックマークをクリックして答えとして受け入れることを検討してください。それはコミュニティがそれが働いたこと、そしてあなたの問題が閉鎖されていることをコミュニティに知らせるものです。 – CPak

答えて

0

foreachはすでにループ動作を提供し、(あなたが指定することができます)出力を組み立てるしようとします。

あなたのデータ:

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) 

新しいコード:loopforeachの各々において

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) 

、行によってmy.dfを反復。次に%do%次のようになります。rbindHeader()substring...となり、data.frameになります。最後に.combineの出力はrbindです。これにより、単一の列データフレームが生成されます。 write_tsv...で出力ファイルに書き込みます。

出力:

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

------単に%dopar%%do%を置き換える、並列化する--------

を並列化します。あなたが持っているエントリーの数によっては、実際には%do%がもっと速いかもしれません。

+0

@Chi Pakさん、実際の(もっと複雑な)関数でこれを動作させるのにはしばらく時間がかかりましたが、小さなテストセットでウォーキングしているようです。クラスタ上の実際のデータ。 – user8173816

+0

メモリの問題が発生したときは、次のいずれかの操作を行うことができます。A)各行をすぐにファイルに書き込む(つまり、大きなR構造にアセンブルしない)か、またはB)入力ファイルを小さなバッチに分割する。より具体的なヘルプが必要な場合は、新しい質問を投稿する必要があります。 – CPak

関連する問題