欢迎学习本课程

用 Rcpp 优化 R 代码

Romain François

Consulting Datactive, ThinkR

R 与 C++ 对比

R

  • 强大、灵活
  • 较慢
  • 解释型

C++

  • 编译型
  • 较难
  • 快速
用 Rcpp 优化 R 代码

学习动机

  • 用 Rcpp 加速你的代码
  • 无需精通全部 C++
  • 重点是编写简单的 C++ 函数
用 Rcpp 优化 R 代码

课程结构

  • 入门:基础 C++ 语法
  • C++ 函数与控制流
  • 向量类
  • 案例研究
用 Rcpp 优化 R 代码

测量性能

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
用 Rcpp 优化 R 代码
用 Rcpp 优化 R 代码

用 evalCpp 求值简单的 C++ 表达式

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}$)

用 Rcpp 优化 R 代码

基本数值类型

C++ 拥有丰富的数值类型

  • 整数:int
  • 浮点数:double
用 Rcpp 优化 R 代码

R

# 字面量数字为 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"
用 Rcpp 优化 R 代码

类型转换

使用 (double) 显式类型转换

# 显式转换
y <- evalCpp("(double)(40 + 2)")
storage.mode(y)
"double"

注意整数除法

# 整数除法
evalCpp( "13 / 4" )
3

 

# 显式转换,因此使用
# 浮点除法
evalCpp( "(double)13 / 4" )
3.25

 

# R 中的自动转换
13L / 4L
3.25
用 Rcpp 优化 R 代码

让我们练习!

用 Rcpp 优化 R 代码

Preparing Video For Download...