R 中的字节编译器优化
Byte Compiler-optimisation in R
考虑 R 中的以下代码
####### CODE 1 #######
test = FALSE # or TRUE
for (i in 1:10^5){
if (test){
DoThat(i)
} else {
DoThis(i)
}
}
如果 R 编译器很好,我希望 if
语句的条件不会在每次迭代时都被评估。 Code 1
将等同于
####### CODE 2 #######
test = FALSE # or TRUE
if (test){
for (i in 1:10^5){
DoThat(i)
}
} else {
for (i in 1:10^5){
DoThis(i)
}
}
Code 1
更容易阅读,但如果编译不好会比 code 2
慢
这两个代码编译后是否等价(计算时间)?我是否应该确保将我的代码包含到一个函数中(最终是一个名为 main
的函数)以确保编译得到很好的优化?
仅供参考:我的 R 版本是 R 3.1.2 GUI 1.65 Mavericks build (6833)
这似乎是您可以轻松地对自己进行基准测试的东西(我会在组合中加入另一个选项
DoThis<-function(x) x+2
DoThat<-function(x) x+1
f1<-function() {
test = FALSE # or TRUE
for (i in 1:10^5){
if (test){
DoThat(i)
} else {
DoThis(i)
}
}
}
f2<-function() {
test = FALSE # or TRUE
if (test){
for (i in 1:10^5){
DoThat(i)
}
} else {
for (i in 1:10^5){
DoThis(i)
}
}
}
f3<-function() {
test = FALSE # or TRUE
if (test){
fn<-DoThat
} else {
fn<-DoThis
}
for (i in 1:10^5){
fn(i)
}
}
然后与
比较
library(microbenchmark)
microbenchmark(f1(),f2(),f3())
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# f1() 55.44489 57.79875 61.50379 60.65098 62.25607 118.8442 100 b
# f2() 42.70537 44.30422 52.45846 46.37495 48.51268 499.1535 100 ab
# f3() 41.59938 42.92486 47.29460 46.02898 47.50596 117.2711 100 a
如您所见,它们在微秒级上的 运行 时间大致相等。
如果您通过 compiler::cmpfun
"compile" 他们,结果不会有太大变化
f1c = compiler::cmpfun(f1)
f2c = compiler::cmpfun(f2)
f3c = compiler::cmpfun(f3)
microbenchmark(f1c(),f2c(),f3c())
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# f1c() 42.39095 45.59775 50.22462 47.38297 49.73408 132.88284 100 b
# f2c() 41.79704 43.79836 46.87072 44.98536 48.21903 126.02609 100 a
# f3c() 40.07256 42.33789 45.14435 44.16019 46.32952 66.53634 100 a
测试:R 版本 3.1.0 (2014-04-10),平台:x86_64-apple-darwin10.8.0(64 位)
考虑 R 中的以下代码
####### CODE 1 #######
test = FALSE # or TRUE
for (i in 1:10^5){
if (test){
DoThat(i)
} else {
DoThis(i)
}
}
如果 R 编译器很好,我希望 if
语句的条件不会在每次迭代时都被评估。 Code 1
将等同于
####### CODE 2 #######
test = FALSE # or TRUE
if (test){
for (i in 1:10^5){
DoThat(i)
}
} else {
for (i in 1:10^5){
DoThis(i)
}
}
Code 1
更容易阅读,但如果编译不好会比 code 2
这两个代码编译后是否等价(计算时间)?我是否应该确保将我的代码包含到一个函数中(最终是一个名为 main
的函数)以确保编译得到很好的优化?
仅供参考:我的 R 版本是 R 3.1.2 GUI 1.65 Mavericks build (6833)
这似乎是您可以轻松地对自己进行基准测试的东西(我会在组合中加入另一个选项
DoThis<-function(x) x+2
DoThat<-function(x) x+1
f1<-function() {
test = FALSE # or TRUE
for (i in 1:10^5){
if (test){
DoThat(i)
} else {
DoThis(i)
}
}
}
f2<-function() {
test = FALSE # or TRUE
if (test){
for (i in 1:10^5){
DoThat(i)
}
} else {
for (i in 1:10^5){
DoThis(i)
}
}
}
f3<-function() {
test = FALSE # or TRUE
if (test){
fn<-DoThat
} else {
fn<-DoThis
}
for (i in 1:10^5){
fn(i)
}
}
然后与
比较library(microbenchmark)
microbenchmark(f1(),f2(),f3())
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# f1() 55.44489 57.79875 61.50379 60.65098 62.25607 118.8442 100 b
# f2() 42.70537 44.30422 52.45846 46.37495 48.51268 499.1535 100 ab
# f3() 41.59938 42.92486 47.29460 46.02898 47.50596 117.2711 100 a
如您所见,它们在微秒级上的 运行 时间大致相等。
如果您通过 compiler::cmpfun
"compile" 他们,结果不会有太大变化
f1c = compiler::cmpfun(f1)
f2c = compiler::cmpfun(f2)
f3c = compiler::cmpfun(f3)
microbenchmark(f1c(),f2c(),f3c())
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# f1c() 42.39095 45.59775 50.22462 47.38297 49.73408 132.88284 100 b
# f2c() 41.79704 43.79836 46.87072 44.98536 48.21903 126.02609 100 a
# f3c() 40.07256 42.33789 45.14435 44.16019 46.32952 66.53634 100 a
测试:R 版本 3.1.0 (2014-04-10),平台:x86_64-apple-darwin10.8.0(64 位)