使用字节码编译器

在上一节中,我们介绍了向量化的强大之处。然而,有时候难以使用向量化解决某些
问题,必须使用 for 循环。在这种情况下,我们可以考虑使用字节代码编译器来编译函数,
就不需要对函数进行解析,运行速度也会更快。
首先,我们加载编译器的包,它是随 R 一起发布的。使用 cmpfun( ) 函数编译一个
给定的 R 函数。例如,编译 diff_for( ),然后保存结果,并命名为 diff_cmp( ):
library(compiler)
diff_cmp <- cmpfun(diff_for)
diff_cmp
## function(x) {
## n <- length(x) - 1
## res <- numeric(n)
## for (i in seq_len(n)) {
## res[[i]] <- x[[i + 1]] - x[[i]]
## }
## res
## }
## <bytecode: 0x93aec08>
当查看函数 diff_cmp( ) 时,我们发现与 diff_for( ) 相比,它并没有什么特别
之处,只是最后多了一串字节码(bytecode)地址。
接下来,我们对 diff_for( ) 进行基准测试:
x <- rnorm(10000)
microbenchmark(diff_ _for(x), diff_ _cmp(x), diff(x))
## Unit: microseconds
## expr min lq mean median
## diff_for(x) 10664.387 10940.0840 11684.3285 11357.9330
## diff_cmp(x) 732.110 740.7610 760.1985 751.0295
## diff(x) 80.824 91.2775 107.8473 103.8535
## uq max neval cld
## 12179.98 16606.291 100 c
## 763.66 1015.234 100 b
## 115.11 219.396 100 a
结果令人惊讶,尽管我们没有进行任何改动,只是将函数编译成字节码,但经过编译
的版本 diff_cmp( ) 比 diff_for( ) 要快得多。
现在,我们对函数 algo1_for( ) 进行同样的操作:
algo1_cmp <- cmpfun(algo1_for)
algo1_cmp
## function(n) {
## res <- 0
## for (i in seq_len(n)) {
## res <- res + 1 / i ^ 2
## }
## res
## }
## <bytecode: 0xa87e2a8>
然后对编译版本和原版函数进行测试:
n <- 1000
microbenchmark(algo1_ _for(n), algo1_ _cmp(n), algo1_ _vec(n))
## Unit: microseconds
## expr min lq mean median uq
## algo1_for(n) 490.791 499.5295 509.46589 505.7560 517.5770
## algo1_cmp(n) 55.588 56.8355 58.10490 57.8270 58.7140
## algo1_vec(n) 8.688 9.2150 9.79685 9.4955 9.8895
## max neval cld
## 567.680 100 c
## 69.734 100 b
## 19.765 100 a
结果与之前相似,编译版本比原版快了 6 倍多,即使我们没有对代码进行任何改动。
然而,当我们编译一个完全向量化的函数时,它就失去了惊人的魔力。这里,我们编
译 algo1_vec( ) 函数,并比较它和原版函数的性能:
algo1_vec_cmp <- cmpfun(algo1_vec)
microbenchmark(algo1_ _vec(n), algo1_ _vec_ _cmp(n), times = 10000)
## Unit: microseconds
## expr min lq mean median uq
## algo1_vec(n) 8.47 8.678 20.454858 8.812 9.008
## algo1_vec_cmp(n) 8.35 8.560 9.701012 8.687 8.864
## max neval cld
## 96376.483 10000 a
## 1751.431 10000 a
我们注意到,编译后的函数在性能上并没有明显提升。如果想了解更多关于编译器的
工作原理,可以输入 ?compile 阅读帮助文档。

posted @ 2019-02-11 14:32  NAVYSUMMER  阅读(167)  评论(0编辑  收藏  举报
交流群 编程书籍