狮山草堂——猪の家分享 http://blog.sciencenet.cn/u/zhumengjin 行为上保守,思想上激进

博文

大数据分析中提升R速度的几点tips

已有 23530 次阅读 2016-1-12 23:10 |个人分类:科学研究|系统分类:科研笔记| 建议, 速度

       基因组学的处理对象一般都是大数据。在基因组学领域,R语言以其易理解、好学、上手快、免费、网上可借鉴资源多的特点,越来越受到广大普通科研工作者的青睐。对于统计分析,相对于其他软件和工具,目前全世界R的用户规模应该是排在第一位的。在发表的各类科研论文中,R经常亮出其靓丽的身影,R在世界范围内产生的巨大影响力不容小觑。事实上,很多学者也意识到这一趋势,很多分析工具的开发者,想提高其工具的影响力,扩大其工具的使用范围,都不得不开发出相应的R版本,比如统计基因组学领域的经典分析软件DMU、ASREML都开发出了相应的R版。

       不过,R的缺点也很明显,那就是相对于C/C++、Fortran等,R的计算速度相对更慢。当然,对于计算速度,算法才是王道。不过,即使在算法没有大的改进的情况下,适当掌握R的编程技巧,即便是处理大数据的基因组学问题,速度也不是个问题。统计基因组学领域最普遍使用的是线性模型分析技术。经过一些R爱好者的努力,在线性模型的计算领域,目前已基本实现了C语言与R的无缝对接,如Rcpp、RcppEigen、RcppArmadillo等包的出现,极大地提升了R处理线性模型的速度,一些基于Rcpp、RcppEigen、RcppArmadillo包的处理特定线性模型问题的“二级”包也越来越多。所以,对于一般数据的处理,甚至是Big data的处理,R已经完全可以胜任。当然,对于矩阵维数达到数千万维的超大数据集,R目前仍然有些乏力。

       下面是提升R速度的几点tips:

     (1)对于估计线性模型参数的包,直接或选用依赖于Rcpp、RcppEigen、RcppArmadillo的packages,因为这些包通过调用C library进行计算,速度更快。

     (2)避免使用for这样的显式循环语句,尽可能改用向量化(vectorization)的语句,只要能最大化地实现R计算过程的向量化,R的计算速度绝对不容鄙视。如按列求矩阵的和,循环命令for (i in ncol(X)) {A[i]<-mean(X[,i])},要慢于apply(X, 2, mean)或者colSums(X)。这里需要说明的是,for循环语句慢的问题,只是在大数据的时候才能体现出来,对于一般的数据,在某些情况下for循环命令甚至有可能更快。 

    (3)可以完成同样任务的命令,一般优先使用base包提供的命令,因为base包的命令是经过优化的,速度有保障,除非是专门优化过(如利用C library)的命令。

    (4)另外,base包中有些primitive functions经过.Primitive定义之后,新定义的函数有可能比原来的函数快5-10倍,比如:mysqrt <- .Primitive("sqrt"),相较于原来的sqrt,mysqrt的速度会有明显提升:

    (5)关于加()提升R速度的小技巧,正常情况下,在一个计算公式中,对于需要计算的中间变量,适当加上()可以略微提升速度,比如(B*C)/(abs(A))要比B*C/abs(A)稍微快那么一丁点儿。特别是在大数据的统计基因组学领域,这个“一丁点儿”在几百万、几千万的循环中的累积效应不可忽视。

    (6)循环中适当地释放内存,也可以提升速度。比如在适当的位置插上rm(object)、gc()命令,可以释放内存,加快速度,提高内存利用效率,避免普通机子的frozen现象。

    (7)在处理大数据时,对于很多循环结构,不能或较难向量化(vectorization)处理,这时也不要用for这样的显式循环语句,而是用多核并行运算的方式来处理(现在一般普通台式机都是多核的),这样既解决了循环的问题,又用到了并行运算,速度自然会有明显的提升。需要注意的是,由于并行计算在结束后内部有一个“合并”结果的过程,这需要耗费时间,对于一般规模的数据,其速度并不一定会有提升,并行计算适合大数据。现给出一个并行计算的例子,如用固定线性模型(fixed linear model)在基因组范围内开展SNPs对表型的线性回归(相当于PLINK),R至少有数十个packages可以实现,但速度最快的是调用了C library的RcppEigen、RcppArmadillo等packages,要比regress等常规packages快N个数量级,再加上多核并行运算,速度会有质的提升:

    >library(doParallel)
    >library(foreach)  
    >num<-detectCores()
    >cl <- makeCluster(num)
    >registerDoParallel(cl)
    >dd<-foreach(i = 1:ncol(X), .packages= 'RcppEigen', .combine = 'rbind') %dopar% { Model<- fastLmPure(y = y, X = as.matrix(cbind(rep(1, length(y)), X[, i]))); c(Model$coefficients[2])}
    >stopCluster(cl)

    (8)提升R运算速度的另一小技巧,程序中所用函数的parameter option尽可能给出,省去R运行时判断是否用default选项,这也可能提升速度。

    (9)矩阵初始化到位的问题。如果循环中涉及矩阵的储存,那么A<-matrix()不如A<-matrix(0, nrow, ncol),循环中A<-cbind(A, c)要比A[,i]<-c慢很多。

    (10)初级的常识性的东西,但R的初学者往往忽略,在循环或重复时,对于不需要动态更新的中间变量,不要放到循环、重复过程中去处理,而要放在循环或重复外,这样可以节约大量的时间。

      因为统计基因组学的分析对象一般都是大数据,所以任何一丁点儿微小的提升,最后的效果将是很可观的。



https://blog.sciencenet.cn/blog-295006-950002.html

上一篇:桃李成蹊十八载,和风细雨润无声——纪念我的恩师
下一篇:什么是大学教授?
收藏 IP: 220.249.99.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (1 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-12-22 00:10

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部