Tối ưu hóa mã R với Rcpp
Romain François
Consulting Datactive, ThinkR
R
C++
phiên bản dùng vòng lặp của max
slowmax <- function(x){
res <- x[1]
for ( i in 2:length(x) ){
if( x[i] > res ) res <- x[i]}
res }
So sánh hiệu năng với 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
Sử dụng
std::numeric_limits<int>::max()
để lấy số nguyên có dấu 32-bit (int) lớn nhất có thể biểu diễn
evalCpp(
"std::numeric_limits<int>::max()"
)
2147483647
( $\footnotesize \mathtt{2147483647 = 2^{31}-1}$)
C++ có bộ kiểu số phong phú
intdoubleR
# Số literal là double
x <- 42
storage.mode(x)
"double"
# Số nguyên cần hậu tố L y <- 42L storage.mode(y)z <- as.integer(42) storage.mode(z)
"integer"
"integer"
C++
# Hậu tố .0 ép thành double
y <- evalCpp( "42.0" )
storage.mode(y)
"double"
library(Rcpp)
# Số nguyên literal là int
x <- evalCpp( "42" )
storage.mode(x)
"integer"
Ép kiểu tường minh với (double)
# Ép kiểu tường minh
y <- evalCpp("(double)(40 + 2)")
storage.mode(y)
"double"
Cẩn thận với phép chia số nguyên
# Chia số nguyên
evalCpp( "13 / 4" )
3
# Ép kiểu tường minh, do đó dùng
# phép chia double
evalCpp( "(double)13 / 4" )
3.25
# Chuyển đổi tự động trong R
13L / 4L
3.25
Tối ưu hóa mã R với Rcpp