众所周知,R的速度绝对算不上快,由它是解释型语言决定的。解决小数据还行,但是大数据也并不是没有办法,大多数时候是自己的代码不够高效,比如说重复计算,频繁更改数据等。
复习一下:解释型语言(Interpreted language)是一种编程语言类型。这种类型的编程语言,会将代码一句一句直接运行,不需要像编译语言(Compiled language)一样,经过编译器先行编译为机器代码之后再运行。这种编程语言需要利用解释器,在运行期,动态将代码逐句解释(interpret)为机器代码,或是已经预先编译为机器代码的子程序,之后再运行。
理论上,任何编程语言都可以是编译式,或解释型的。它们之间的区别,仅与程序的应用有关。许多编程语言同时采用编译器与解释器来实现,其中包括Lisp,Pascal,C,BASIC 与 Python。JAVA及C#采用混合方式,先将代码编译为字节码,在运行时再进行解释。
参考:维基百科
利用的编译包:compiler
这个包旨在解决代码丑陋、低效的问题
原理:The function cmpfun
compiles the body of a closure and returns a new closure with the same formals and the body replaced by the compiled body expression.
R其实默认开启了just-in-time(JIT)编译,所以为了演示编译前后的差别,先关掉JIT enableJIT(0)
- 无需安装,R自带
library(compiler)
即可 - 示例
library(compiler)
library(microbenchmark)
mean_r = function(x) {
m = 0
n = length(x)
for(i in seq_len(n))
m = m + x[i] / n
m
}
cmp_mean_r = cmpfun(mean_r)
x = rnorm(10000)
microbenchmark(times = 10, unit = "ms", # milliseconds
mean_r(x), cmp_mean_r(x), mean(x))
Unit: milliseconds
expr min lq mean median uq max neval cld
mean_r(x) 4.395102 4.485002 4.5013910 4.506701 4.519601 4.616402 10 c
cmp_mean_r(x) 0.420501 0.422701 0.4247412 0.424401 0.426301 0.429502 10 b
mean(x) 0.020502 0.021802 0.0279112 0.029301 0.031101 0.040000 10 a
上面的是efficient-r-programming官方给出的例子,我们自己编一个函数试试看,涵盖禁忌:for 循环,频繁更改数据
method1 <- function(n) {
x = runif(n) + 1
log_sum = 0
for(i in 1:length(x))
log_sum = log_sum + log(x[i])
}
method2 <- function(n) {
x = runif(n) + 1
log_sum = 0
log_sum = sum(log(x))
}
method3 <- cmpfun(method1)
#试试
> microbenchmark(times = 10, unit = "ms",
method1(1000000), method2(1000000),method3(1000000))
Unit: milliseconds
expr min lq mean median uq max neval cld
method1(1e+06) 490.2590 492.7608 500.95412 494.4149 498.7615 551.7498 10 c
method2(1e+06) 57.0103 57.0812 57.29056 57.2680 57.4692 57.7043 10 a
method3(1e+06) 106.1837 106.3250 106.82335 106.3792 107.0097 109.3710 10 b
#加大数据量?
> microbenchmark(times = 10, unit = "ms",
method1(100000000), method2(100000000),method3(100000000))
Unit: milliseconds
expr min lq mean median uq max neval cld
method1(1e+08) 49443.231 49629.365 49823.064 49823.442 49997.07 50313.719 10 c
method2(1e+08) 5917.398 6006.092 6024.268 6014.849 6036.85 6161.088 10 a
method3(1e+08) 10649.740 10727.456 10804.565 10810.447 10878.22 10973.379 10 b
效果不错,快了近五倍
补充:install.packages()
安装的大多数包都是未经编译的,可以强制
install.packages("ggplot2", type = "source", INSTALL_opts = "--byte-compile")
或者你愿意折腾,去修改.Renviron文件中的R_COMPILE_PKGS为正值