机器学习与数据挖掘重点实验室
R 和 C 语言、C++ 语言函数调用
-----开发平台建设·基础篇(6)
机器学习与数据挖掘重点实验室
刘江伟
(majorliujw◎gmail.com)
2014-5-18
实验说明
关键词:R; C;C++;DLL;编译运行效率;.Call ;Rcpp 包;inline 包
摘 要:
1)如何 用 R 调用 C 函数,使底层运算(如循环等)速度加快。
2)R 和 C++各自优势如何对接起来(如 R 的矩阵运算,向量运算以及各种统计算法等;C++
的底层运算速度,标准库函数 STL 等)。
3)本实验以操作为主。
实验一:R 语言和 C 语言 函数调用
实验目的:如何 用 R 调用 C 函数,使底层运算(如循环等)速度加快。
1.下载 Rtools:
(如 Rtools30.exe);
2.添加环境变量 path:
添加 R 环境变量:
机器学习与数据挖掘重点实验室
D:\Program Files\R\R-3.0.2\bin\i386(要用到这个路径下的 Rcmd.exe)
添加 RTools 环境变量:
D:\Program Files\Rtools\bin;
D:\Program Files\Rtools\gcc-4.6.3\bin
配置完后,在 CMD 窗口输入以后命令,用来测试环境变量是否 OK!
gcc --help
Rcmd
Rcmd SHLIB --help
3.编写 testR.c 文件:
R 和 C 传递数据都是指针形式。
其中数据类型对应如下:
testR.c 文件
/////////////////////////////////////////////////////////////////////
///////////////////////////////
#include
void myadd(double *a, double *b, double *c)
{
*c=*a+*b;
}
void myprint(const char **msg){
Rprintf("msg is: %s",*msg);
}
//double 型数据
void myMultiAdd1 (double *n, double *prod, const char **msg) {
机器学习与数据挖掘重点实验室
* prod=0;
int i,j,k;
for(i=1;i<=*n;i++)
for(j=1;j<=*n;j++)
for(k=1;k<=*n;k++)
*prod=*prod+(i+j+k);
Rprintf("%s 说,%f 以内所有数(可重复)相加的结果
是: %f\n",*msg,*n,*prod);
}
//只是换数据类型;测试数据比较大时,可以用 long int,或者 long long int
void myMultiAdd2 (int *n, long long int *prod, const char **msg) {
*prod=0;
int i,j,k;
for(i=1;i<=*n;i++)
for(j=1;j<=*n;j++)
for(k=1;k<=*n;k++)
*prod=*prod+(i+j+k);
Rprintf("%s 说,%d 以内所有数(可重复)相加的结果
是: %d\n",*msg,*n,*prod);
}
/////////////////////////////////////////////////////////////////////
///////////////////////////////
4.生成 dll:
把 testR.c 放到 F 某个盘文件夹下,windows cmd cd 到这个文件夹去
Rcmd SHLIB testR.c 命令,生成 testR.dll 和 testR.o 两个文件。 .dll 文件成
功生成~~
把 testR.dll 拷贝到你的 R 工程目录
5.R 文件中测试及调用:
RC.R 文件
#################################################
## R 调用 C 函数方法
## 优点:C 运行时间大大减少;特别是循环之类的情况。
## C 编译 DLL 命令: Rcmd SHLIB testR.c
##################################################
##-----------------------R 循环函数--------------------------
myMultiAdd<-function(n){
num=0;
for(i in 1:n)
for (j in 1:n)
for (k in 1:n)
{
num=num+(i+j+k);
机器学习与数据挖掘重点实验室
}
cat("R 的循环结果为:",num,"\n");
}
#myMultiAdd(3) #测试
#加载动态链接库
dyn.load('testR.dll')
##-----------------简单函数调用---------------
.C("myadd", as.numeric(1.2),as.numeric(3.4),as.numeric(1))
.C("myprint", as.character("hello, world"))
##-----------------注意数据类型---------------
#R 默认的数据类型是 double
.C("myMultiAdd1",a1=3,b1=0,c1="Master1")
#以整数调用;注意 C 函数的整型数据表示范围,
a2=as.integer(3);
b2=as.integer(0);
.C("myMultiAdd2",a2,b2,c2="Master2")
##-----------------测试时间,C 和 R 时间差别---------------
system.time(myMultiAdd(150))
a2=as.integer(150);
b2=as.integer(0);
system.time(.C("myMultiAdd2",a2,b2,c2="C 语的结果"))
#卸载动态链接库
dyn.unload("testR.dll")
6.主要循环时间对比:
通过一个三重循环对比了 R 和 C 的运行时间,R 大约是 8 秒多,C 函数大约 0.02
秒,如图所示。
机器学习与数据挖掘重点实验室
实验二:R 语言和 C++ 语言 函数调用
实验目的:
1)R 和 C++各自优势如何对接起来(如 R 的矩阵运算,向量运算以及各种统计算法等;C++
的底层运算速度,标准库函数 STL 等) 。安装 RTools 之后,自动安装了 g++编译器,直接
使用 RStudio 编写,C++ code 和 R code。
2).Call ;Rcpp 包;inline 包
3)本次试验以操作为主
方式一:Rcpp API 方式调用 (library("Rcpp"))。
-----------------// C++ code 开始----------------------------
//Rcpp API 方式调用
#include
RcppExport SEXP convolve3cpp(SEXP a, SEXP b) {
Rcpp::NumericVector xa(a);
Rcpp::NumericVector xb(b);
int n_xa = xa.size(), n_xb = xb.size();
int nab = n_xa + n_xb - 1;
Rcpp::NumericVector xab(nab);
for (int i = 0; i < n_xa; i++)
机器学习与数据挖掘重点实验室
for (int j = 0; j < n_xb; j++)
xab[i + j] += xa[i] * xb[j];
return xab;
}
-----------------------// C++ code 结束--------------------------
-----------------# Rcode 开始----------------------------
#Rcpp API 方式调用
library("Rcpp");
##Rcpp API 方式调用
f3 <- function(x,y) .Call("convolve3cpp", x,y);
f3(1:3,1:4)
-----------------------# R code 结束--------------------------
方式二:直接在 R 中嵌入 C++代码(使用到了 inline 包)。
##-----------------------------------------------inline 方式 开始
-----------------------------------------------
src<-'
Rcpp::NumericVector xa(a);
Rcpp::NumericVector xb(b);
int n_xa = xa.size(), n_xb = xb.size();
int nab = n_xa + n_xb - 1;
Rcpp::NumericVector xab(nab);
for (int i = 0; i < n_xa; i++)
for (int j = 0; j < n_xb; j++)
xab[i + j] += xa[i] * xb[j]; //注意是"+="
return xab;
' ;
# cxxfunction(provided by the inline package),
fun <- cxxfunction(signature(a = "numeric", b = "numeric"),
src,
plugin = "Rcpp")
fun(1:3, 1:4)
#结果是 [1] 1 4 10 16 17 12
##—————Using Standard Template Library
algorithms—————————
# 用 STL 库中的 transform 模拟 R 中的 lapply
src <- '
Rcpp::List input(data);
Rcpp::Function f(fun);
Rcpp::List output(input.size());
std::transform(input.begin(), input.end(), output.begin(), f);
output.names() = input.names();
机器学习与数据挖掘重点实验室
return output;
' ;
cpp_lapply <- cxxfunction(signature(data = "list", fun = "function"),
src, plugin = "Rcpp")
## 用 R 中的 faithful 数据集测试;summary 查看数据集
cpp_lapply(faithful, summary)
#-----------------------------------------------------------inline 方
式 结束 --------------------------------------------
参考文献
[1] Rcpp: Seamless R and C++ Integration ver.2014
[2] 网络资源