在函数定义中使用foreach而不是使用foreach写入文件

时间:2017-07-13 17:41:50

标签: r foreach parallel-processing doparallel

在编写文件时,我很难并行化R以优化函数调用的速度。功能很简单,但它创建的文件非常庞大,并且需要花费不合理的时间。我一直在使用profvis来可视化时间的去向,并且看起来嫌疑人在函数结尾的cat语句中,以及在写入输出文件时的捕获步骤中。我在下面包含了一个简化的,小的,可重现的示例脚本,但实际文件很大,我在超级计算集群上运行它们。并行运行脚本并没有给我任何速度提升,但是我对如何构造foreach语句感到不知所措,以便它实际上并行捕获函数的每次迭代。将foreach放入函数本身会给我带来订单问题(而不是标题,基本削减,标题,基数对等,它会随机附加它们 - 但它们碰巧已经从它们运行的​​任何核心中脱落)并将其放入capture.output行,实际上似乎没有做任何事情。

预期输出:

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}

1 个答案:

答案 0 :(得分: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) 

新代码:

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)

loop的每个foreach中,按行迭代my.df。然后%do%以下rbind Header()substring...,然后转为data.frame。最后,.combine输出rbind。这将生成单列数据帧。使用write_tsv...写入输出文件。

输出:

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

<强> ------ --------并行

要进行并行化,只需将%do%替换为%dopar%即可。根据您拥有的条目数量,%do%实际上可能更快。