考虑以下函数foo
和bar
(仅在打印警告方面有所不同)及其R等效fooR
和barR
:
cppFunction('
void foo () {
int i = 0;
while (i < 1e3) {
i++;
}
return;
}')
cppFunction('
void bar () {
int i = 0;
while (i < 1e3) {
i++;
Rcpp::warning("hello world!");
}
return;
}')
fooR <- function() {
i = 0;
while (i < 1e3) {
i = i+1;
}
}
barR <- function() {
i = 0;
while (i < 1e3) {
i = i+1;
warning("hello world!")
}
}
显然,打印警告会使功能变慢,但R和Rcpp之间的差异很大(慢200倍,慢5000倍!):
> benchmark(foo(), bar())
test replications elapsed relative user.self sys.self user.child sys.child
2 bar() 100 5.156 5156 5.156 0 0 0
1 foo() 100 0.001 1 0.000 0 0 0
There were 50 or more warnings (use warnings() to see the first 50)
> benchmark(fooR(), barR())
test replications elapsed relative user.self sys.self user.child sys.child
2 barR() 100 11.102 213.5 11.104 0 0 0
1 fooR() 100 0.052 1.0 0.052 0 0 0
There were 50 or more warnings (use warnings() to see the first 50)
为什么会这样?可以预防吗?
答案 0 :(得分:3)
我不确定您是否从基准中了解到Rcpp
是:
现在,当您在 Rcpp
和base R
中发出警告时,会发生以下情况:
STDERR
的流。 (因此,红色文字而不是STDOUT
的黑色)STDERR
在Rcpp
中,低级引用有助于降低重复上述过程所需的总时间,并将控制权返回到循环中,而R'处理程序位于堆栈的更高位置。
同样,使用Rcpp完成此操作所需的时间是正常的,因为它必须将进程的控制权交还给R,打印消息,然后返回循环。考虑纯循环情况下速度损失的最佳方法是,您决定在C ++循环中调用基于R的函数,而不是期望加速的R循环。
说实话,我有点惊讶Rcpp
能够比R等同物快2倍。