我使用R
包在deSolve
中解决ODE问题。为了加快计算,我想使用编译代码,使用说明here
我在下面展示了ODE系统的一个例子 - 我正在使用下面的Rcpp
进行编码。 ODE系统的详细信息来自示例MATLAB
代码(可以找到here)。我想模拟一组非平凡的ODE,以便仅查看R
和编译代码的差异。以下是我的驱动文件,我用两种不同的方式计算了质量平衡(仅R
和编译代码)
library(deSolve)
library(ggplot2)
library(microbenchmark)
source('parameters_gprotein.R')
p <- parameters()
source('IC_gprotein.R')
IC <- Initial_conditions()
TIME = seq(from = 0, to = 600)
source('odes_gprotein.R')
sim.data.df <- as.data.frame(vode(IC,TIME,ODE_gprotein,p,
mf = 22, rtol=1e-3,atol=1e-6,maxord = 5,
verbose = F))
Rcpp::sourceCpp("odes_gprotein.cpp")
sim.data.df <- as.data.frame(vode(IC,TIME,odes_gprotein,p,
mf = 22, rtol = 1e-3, atol = 1e-6, maxord = 5,
verbose = F))
我的问题是vode
来自R
。这是否意味着如果在cpp
中形成质量平衡并实现速度增益,则在编译代码中求解方程式,或者我是否还必须在vode
文件中进行cpp
调用
当然,微基准测试结果显示使用odes_gprotein.cpp
Unit: milliseconds
expr
sim.data.df1 <- as.data.frame(vode(IC, TIME, ODE_gprotein, p, mf = 22, rtol = 0.001, atol = 1e-06, maxord = 5, verbose = F))
sim.data.df2 <- as.data.frame(vode(IC, TIME, odes_gprotein, p, mf = 22, rtol = 0.001, atol = 1e-06, maxord = 5, verbose = F))
min lq mean median uq max neval
27.801954 29.543624 31.213758 30.565434 31.399140 86.28537 100
8.188846 8.577824 9.177491 8.817025 9.437214 18.94304 100
由于
答案 0 :(得分:3)
将来,请链接到/提供问题所依据的所有书面代码。
在编写R和Rcpp函数代码的比较时,应附加到c ++函数名_cpp
的末尾,以便明确调用不同的实现。例如C ++实现是ODE_gprotein()
还是odes_gprotein()
?
在基准测试的情况下,似乎odes_gprotein()
是cpp()
调用,因为微基准测试较低。这意味着vode()
函数正在通过Rcpp::sourceCpp
调用引入命名空间的Rcpp包装器。
如果可能,所有代码都应嵌入cpp
以获得最大收益。这意味着如果速度是一个重要因素(例如,处理非常大的数据或执行计算密集型模拟),您可能必须从头开始实施。该建议是由于减少了R代码前端和C ++代码之间的中继。本质上,当从R调用C ++代码时,有时必须将对象复制并重新格式化为幕后的不同对象,然后才能对其进行处理。如果您使用默认Rcpp类型之外的对象(例如RcppArmadillo,RcppGSL等),则情况尤其如此,因为必须从R的对象结构到导入结构进行复制。
Rcpp::sourceCpp
(幕后)让我们更深入地了解Rcpp::sourceCpp()
背后的实际情况。具体地,当调用该方法时,提取不同的属性(例如// [[Rcpp::]]
标签)并且启用它们的选项。
最常见的标记是// [[Rcpp::export]
,它在C ++代码周围创建一个包装器或一个抽象层,以便它可以轻松地使用R对象。此行为很重要有三个原因:1。您无需担心SEXP类型和内存保护,2。使用默认.Call("fname")
自动创建R级函数,以及3.启用已编译代码的代码缓存只在改变时重新编译。
因此,当您调用odes_gprotein()
时,您实际上正在调用C ++函数。