作者:Valerie Obenchain(vobencha@fredhutch.org.)、马丁·摩根(mtmorgan@fredhutch.org.)
日期:2015年7月22日
本节的目标是突出显示正确,强大,高效的R代码的实践。
相同的()
那All.Equal()
)NA
价值观,......系统时间()
或者是Microbenchmark.包裹。Rprof ()
功能或包装函数lineprof或者4月份矢量化 - 在向量上运行,而不是明确的循环
x <- 1 log(x) ## NOT for (i in seq_along) x[i] <- log(x[i])
## [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101 ## [8] 2.0794415 2.1972246 2.3025851
预先分配内存,然后填写结果
Result [i] <- runif(1): Result [i] <- runif(1) * Result [i - 1] Result
## [1] 0.610156070 0.326579479 0.319540555 0.182668253 0.078093233 ## [6] 0.056413616 0.021594612 0.017351821 0.006025564 0.004570092
为了
环形lm.fit ()
而不是重复地拟合相同的设计矩阵。表格()
那rowSums ()
和朋友,%, %
,…这是一个明显低效的函数:
f0 < -函数(n = 2) {# # stopifnot (is.integer (n) & &(长度(n) = = 1) & & # # ! is.na (n) & & (n > 0))结果< -数字()(我在seq_len (n))结果[[我]]< - *日志(i)结果}
使用系统时间()
调查该算法如何衡量N
,专注于经过的时间。
System.time(F0(10000))
##用户系统运行## 0.150 0.001 0.150
n < - 1000 * seq(1,20,2)t < - sapply(n,function(i)system.time(f0(i))[[3]]图(t〜n,type =“b”)
记住当前的“正确”值,以及近似的时间
n < - 10000 system.time(预期< - f0(n))
##用户系统经过## 0.141 0.000 0.142
(预计)
## [1] 0.000000 1.386294 2.197225 2.772589 3.218876 3.583519
修改呼吸常见乘法器的功能,一种
,不知情。确保“优化”结果与原始计算结果相同。使用Microbenchmark.包以比较两个版本
f1 < - 函数(n,a = 2){for(i在seq_len(n)中)的结果< - numeric()结果[[i]] < - log(i)a *结果}相同(预期,f1(n)))
## [1]真实
库(MicroBenchmark)Microbenchmark(F0(n),f1(n),times = 5)
##单位:毫秒## EXPR分钟LQ平均中值最大UQ ## neval F0(N)98.11787 154.91307 145.9875 158.2557 158.9396 159.7114 5 ## F1(n)的96.93034 97.99369 133.8523 156.3321 158.9998 159.0055 5
采用“预先分配和填补”策略
F2 < - 函数(n,a = 2){结果< - numeric(n)for(i在seq_len(n)中)结果[[i]] < - log(i)a *结果}相同(预期,f2(n))
## [1]真实
微基准测试(f0 (n), f2 (n),时间= 5)
##单位:毫秒:毫秒LQ均值UQ MAX NEVAL ## F0(n)102.20437 162.75624 152.84236 163.095 167.9829 168.21692 5#05/21692 5 #05322(n)11.0532211335959 13.7177611/121135959 13.0532211335959 13.717761133293581C1111177613/13.05322
用A.*申请()
避免必须明确地预先分配的功能,并使矢量化更加明显。
F3 < - 函数(n,a = 2)a * sapply(seq_len(n),log)相同(预期,f3(n))
## [1]真实
微基准测试(f0(n), f2(n), f3(n), times=10)
##单位:毫秒## EXPR分钟LQ平均中值最大UQ ## F0(n)的100.830765 107.964489 145.823291 160.782134 164.901310 166.962340 ## F2(n)的9.370014 11.162675 12.739058 11.709209 15.512331 17.017115 ## F3(n)的4.640934 4.703644 5.799298 5.444969 6.617305 8.305891## Neval ## 10#10 ## 10
既然代码以单行呈现,那么很明显它可以很容易地矢量化。抓住机会向量化它:
F4 <- function(n, a=2) a * log(seq_len(n)) identical(expected, F4 (n))
## [1]真实
Microbenchmark (f0(n), f3(n), f4(n), times=10)
##单位:微秒## EXPR分钟LQ平均中值最大UQ ## F0(n)的101977.842 158804.803 150045.0529 161249.9995 162876.991 165036.864 ## F3(n)的4221.855 4419.104 4925.7432 4651.7185 4885.559 6511.562 ## F4(N)396.465 401.305 412.4188 411.3425 418.137 441.464## Neval ## 10#10 ## 10
F4()
绝对是赢家。它是如何缩放的N
吗?(重复几次)
n < - 10 ^(5:8)#100x大于f0 t < - sapply(n,function(i)system.time(f4(i))[[3]])绘图(t〜n,log =“xy“,type =”b“)
对不同的反应模式有什么解释吗?
经验教训:
*申请()
功能有助于避免需要明确的预分配,并为矢量化的机会更加明显。这可能会出现小的性能成本,但通常是值得的当数据太大而无法适合内存时,我们可以通过块中的文件迭代文件,或者通过字段或基因组位置子集。
迭代-块明智-打开()
,阅读块,close ()
。- 例如,yieldSize
争论RSAMTOOLS :: BAMFILE()
-框架:GenomicFiles :: DreambyByield()
限制 - 限制列和/或兴趣的行 - 利用域特定的格式 - BAM文件和RSAMTOOLS :: SCANBAMPARAM()
- BAM文件和Rsamtools: PileupParam ()
- VCF文件和VariantAnnotation :: scanvcfparam()
- 使用数据库
迭代文件:`genomicfiles :: dreambybyyield()
suppressPackageStartupMessages({库(GenomicFiles)图书馆(GenomicAlignments)图书馆(Rsamtools)库(TxDb.Hsapiens.UCSC.hg19.knownGene)})收益率< - #如何输入的下一块数据函数(X,…){readGAlignments (X)} < - #如何映射到每个块功能(价值,…{olaps <- findoverlap (VALUE, roi, type="within", ignore.strand=TRUE) count <- tabulate(subjectHits(olaps), subjectLength(olaps)) setNames(count, names(roi))}减少<- ' + ' #如何组合映射块
改进:“产出率工厂”保持录入记录多少
exitingFactory < - #返回具有本地状态函数(){n_records < - 0l函数(x,...){aln < - readgalignments(x)n_records << - n_records + length(aln)消息(n_records)aln}}
感兴趣的区域,像BAM文件中的染色体命名。
Exbytx < - Exonsby(txdb.hsapiens.ucsc.hg19.knowngene,“tx”)fl < - “/ home/ubuntu/data/vobencha/largedata/srarchive/hg19_alias.tab”map0 < - read.delim(fl,header= false,stringsasfactors = false)seqlevels(exbytx,force = true)< - setNames(map0 $ v1,map0 $ v2)
通过BAM文件迭代的函数。
count1 <- function(filename, roi) {message(filename) ##创建并打开BAM文件bf <- BamFile(filename, yieldSize=1000000) reduceByYield(bf, yieldFactory(), map, reduce, roi=roi)
在行动
bam <——“/ home / ubuntu /数据/ vobencha LargeData / srarchive / SRR1039508_sorted。count <- count1(bam, exByTx)
类型 | 示例使用 | 名称 | 包 |
---|---|---|---|
请全部 | 范围注释 | Bedfile() |
rtracklayer |
。假发 | 覆盖范围 | WigFile () 那BigWigFile () |
rtracklayer |
.GTF. | 转录模型 | gtffile() |
rtracklayer |
maketxdbfromgff() |
基因组法 | ||
.2bit. | 基因组序列 | TwoBitFile () |
rtracklayer |
.fastq. | 读取和品质 | FastqFile () |
缩短 |
本演讲 | 对齐的阅读 | Bamfile() |
RSAMTOOLS. |
.tbx. | 索引标签分隔 | tabixfile() |
RSAMTOOLS. |
.vcf. | 变体呼叫 | vcffile() |
VariantAnnotation. |
## rtracklayer menagerie suppresspackagestartupmessages(库(rtracklayer))名称(getClass(“rtlfile”)@子类)
## [1]“ucscfile”“gfffile”“bedfile”## [4]“wigfile”“bigwigfile”“chabfile”## [7]“twobitfile”“fastafile”“tabseparatedfile”## [10]“compressurefile”“gff2file”“gff2file”## [13]“gff3file”“bedgraphfile”“bed15file”## [16]“bwfile”“2bitfile”“gtffile”## [19]“gvffile”“gzfile”“bgzfile”##[22]“bz2file”“xzfile”
笔记
打开()
那close ()
那进口()
/屈服()
/读* ()
.Bai.
,BAM指数);选择('列');限制('行')几个警告 -
迭代/限制性技术在控制下保持内存要求,而并行评估在节点上分配计算负载。请记住,并行计算仍然受到每个节点上可用的内存量的限制。
在分布式存储器中计算时,在群集中设置和撕毁群集时,有开销。对于小的计算,并行开销可能超过性能没有提高的好处。
受益于并行执行中最大的作业是CPU密集型,并在适合内存的数据块上运行。
生物相投为并行计算提供标准化接口,并支持主要的并行计算风格:在单个计算机上的分叉和进程、AD hoc集群、批调度程序和云计算。默认情况下,生物相投选择适合操作系统的并行后端,并在UNIX,MAC和Windows中支持。
一般想法:
bpppply()
代替lapply()
争论BPPARAM.
影响平行评估的发生程度
MulticoreParam ()
:单个(非windows)机器上的线程SnowParam()
:在相同或不同的机器上的过程batchjobsparam()
:集群上的资源调度程序doparparam()
:并行执行foreach()
这个小示例激励了并行执行的使用,并演示了如何bpppply()
可以是一下拉普兰人
。
使用系统时间()
以了解执行此操作所需的时间N
从1增加到10。使用相同的()
和Microbenchmark.比较替代方案f0 ()
和F1()
对于正确性和性能。
有趣的
睡眠1秒,然后返回一世
。
# f0 <- function(n) lapply(seq_len(n), fun) ## parallel f1 <- function(n) bplapply(n), fun)
bpredo()
生物相投“捕获并返回”错误以及成功的结果。本练习演示了如何访问追溯()
如何使用' BPREDO '重新运行失败的任务。文档中提供了错误处理、日志记录和调试的详细信息错误、日志和调试装饰图案。
- MulticoreParam(workers = 3
打电话给sqrt()
跨越'x';第二个元素是一个角色,并将抛出和错误。
X <- list(1, "2", 3) res <- bplapply(X, sqrt, BPPARAM = param) res
与错误消息一起,回溯存储在返回列表元素中,并可以访问attr()
:
attr(res [[2]],“回溯”)
通过重复呼叫重新运行失败的结果bpppply()
这次使用的是正确的输入数据和部分结果为' BPREDO '。
x.redo < - list(1,2,3)Bpprapply(x.redo,sqrt,bpredo = res)
生物相投用来徒劳。霍尔格用于记录的包。该软件包具有灵活的系统,用于过滤不同的严重性阈值的消息,例如信息,调试,错误等(对于所有阈值的列表,请参阅?BPThreshold手册页。)生物相投捕获以fution.logger格式编写的消息以及写入stdout和stderr的消息。
此功能有一些参数检查并有调试,警告和信息级日志消息。
FUN <- function(i) {flog.debug(paste0("value of 'i': ", i)) if (!NA} else if (!)一世s(i, "numeric")) { flog.info("coercing to numeric") as.numeric(i) } else { i } }
在参数中打开登录并设置阈值以警告。
param < - snowparam(3,log = true,throupold =“warn”)bplapply(列表(1,“2”,Integer()),Fun,BPParam = Param)
将阈值降低到INFO和DEBUG(即,使用bpthreshold < -
)查看如何在严重性上过滤消息。
对于长时间运行的作业或未经测试的代码,可以设置时间限制很有用。这超时字段是允许每个工人完成一项任务的时间,以秒为单位。如果一项任务比超时worker返回一个错误。
超时可以在参数施工期间设置,
SnowParam <- SnowParam(timeout = 20
##类:SnowParam ## BPJobname:BPJOB;BPWorkers:2;BPTASKS:0;BPTIMOUT:20;bprgseed :;BPISUP:FALSE ## BPLOG:FALSE;BPThreshold:信息;bplogdir:na ## bpstoponerror:false;bpprogressbar:false ## bpresultdir:na ##群集类型:袜子
或者与setter:
bptimout(param)< - 2 param
##类:SnowParam ## BPJobname:BPJOB;BPWorkers:2;BPTASKS:0;bptimout:2;bprgseed :;BPISUP:FALSE ## BPLOG:FALSE;BPThreshold:信息;bplogdir:na ## bpstoponerror:false;bpprogressbar:false ## bpresultdir:na ##群集类型:袜子
使用此函数可以使用“X”值的数值向量探索不同的_timeout_sbpppply()
。'x'值小于超时那些人成功返回阈值返回错误。
有趣< - 函数(i){sys.sleep(i)i}
在工人中分发文件:Genomicfiles :: DreambyFile()
前面使用的计数示例GenomicFiles :: DreambyByield()
在单个文件上运行并实现产量,映射,减少范例。在这项运动中,我们将使用Genomicfiles :: DreambyFile()
哪种用途bplaply()
在引擎盖下,并行地在多个文件上运行。
主要论点dreambybyfile()
是一组文件和一组范围。文件已发送到工人,并且基于范围提取数据子集。这项工作的大部分是在的地图函数和一个可选的减少函数将输出组合在每个工作者上。
suppressPackageStartUpMessages({图书馆(生物竞争)库(GenomicFiles)库(基因组)库(RsamTools)})
在UNIX或Mac上,配置aMulticoreParam ()
有4名工人。打开日志记录并设置60秒的超时。
Param < - MulticoreParam(4,log = true,timeout = 60)
在Windows上做同样的事情SnowParam()
:
(4, log = TRUE, timeout = 60)
指向BAM文件的集合。
FLS < - dir(“/ home / ubuntu / data / data / largedata / copynumber”,“.bam $”,full = true)名称(fls)< - baseName(vs)bfl < - bamfilelist(fls)
定义范围(感兴趣的区域)限制worker上的数据量,并保持对内存需求的控制。我们将使用6号染色体上主要组织相容性复合体位点的一组范围。
range <- GRanges("chr6", IRanges(c(28477797, 29527797, 32448354), c(29477797, 30527797, 33448354)))
这地图功能在记录中读取并计数重叠。ReadGalignments()
在BAM记录中读取与所定义的范围的任何部分重叠Scanbamparam.(即,它们可以重叠开始或结束)。一旦我们有记录R.,我们只想计算那些在范围内的。
地图< - 函数(范围,文件,......){库(基因组)## ReadGalignments(),ScanBamparam()Param = ScanBamparam(哪个=范围)##限制Gal = Readgalignments(文件,Param = Param)##日志消息flog.info(Paste0(“文件:”,baseName(文件)))flog.debug(Paste0(“记录:”,长度(gal)))##重叠OLAP < - footoverlaps(GAL,Range,Type =“在”中,icionore.strand = true)Tabulate(主题(OLAPS),主管长度(OLAP))}
数……
CTS < - DreambyByFile(范围,杂志,地图,BPParam = Param)
结果是一个与文件数量相同长度的列表。
长度(CTS)
每个列表元素是范围数的长度。
ElementLengths(CTS)
每个范围的计数表用'[[]'提取:
CTS [[1]]
GoogleGenomics与Google Compute Cloud和Resources互动
Lawrence,M和Morgan,M. 2014。具有R和Biocumon的可扩展基因组学。统计科学2014年,卷。29,2,214-226。http://arxiv.org/abs/1409.2864v1
生物共争:http://biocidodder.org/packages/release/bioc/html/biocparalles.html.html.
GenomicFiles:http://biocidodder.org/packages/release/bioc/html/genomicfiles.html.