用 Rcpp 最佳化 R 程式碼
Romain François
Consulting Datactive, ThinkR
R
C++
以迴圈實作的 max
slowmax <- function(x){
res <- x[1]
for ( i in 2:length(x) ){
if( x[i] > res ) res <- x[i]}
res }
用 microbenchmark 比較效能
library(microbenchmark)
x <- rnorm(1e6)
microbenchmark( slowmax(x), max(x) )
Unit: milliseconds
expr min lq mean median uq max neval
slowmax(x) 31.649452 34.29454 36.344912 35.435299 37.188249 90.363038 100
max(x) 1.563559 1.74036 1.939367 1.847045 2.014684 3.340052 100
library(Rcpp)
evalCpp( "40 + 2" )
42
evalCpp( "exp(1.0)" )
2.718282
evalCpp( "sqrt(4.0)" )
2
使用
std::numeric_limits<int>::max()
取得 32 位元帶號整數(int)的最大可表值
evalCpp(
"std::numeric_limits<int>::max()"
)
2147483647
( $\footnotesize \mathtt{2147483647 = 2^{31}-1}$)
C++ 有豐富的數值型別
intdoubleR
# 常值數字為 double
x <- 42
storage.mode(x)
"double"
# 整數需加上 L 後綴 y <- 42L storage.mode(y)z <- as.integer(42) storage.mode(z)
"integer"
"integer"
C++
# 後綴 .0 會產生 double
y <- evalCpp( "42.0" )
storage.mode(y)
"double"
library(Rcpp)
# 整數常值為 int
x <- evalCpp( "42" )
storage.mode(x)
"integer"
以 (double) 進行顯式轉型
# 顯式轉型
y <- evalCpp("(double)(40 + 2)")
storage.mode(y)
"double"
留意整數除法
# 整數除法
evalCpp( "13 / 4" )
3
# 顯式轉型,因此使用
# double 的除法
evalCpp( "(double)13 / 4" )
3.25
# R 中的自動轉型
13L / 4L
3.25
用 Rcpp 最佳化 R 程式碼