为什么Rcpp :: warning()比R警告慢?

时间:2016-06-07 10:32:37

标签: r rcpp

考虑以下函数foobar(仅在打印警告方面有所不同)及其R等效fooRbarR

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)

为什么会这样?可以预防吗?

1 个答案:

答案 0 :(得分:3)

我不确定您是否从基准中了解到Rcpp是:

  1. 11.102 / 5.156 = 2.15322倍发出警告
  2. 0.052 / 0.001 = 在纯循环情况下快52倍
  3. 现在,当您在 Rcppbase R中发出警告时,会发生以下情况:

    1. 打开流到STDERR的流。 (因此,红色文字而不是STDOUT的黑色)
    2. 写信息
    3. 关闭STDERR
    4. 继续说明。
    5. Rcpp中,低级引用有助于降低重复上述过程所需的总时间,并将控制权返回到循环中,而R'处理程序位于堆栈的更高位置。

      同样,使用Rcpp完成此操作所需的时间是正常的,因为它必须将进程的控制权交还给R,打印消息,然后返回循环。考虑纯循环情况下速度损失的最佳方法是,您决定在C ++循环中调用基于R的函数,而不是期望加速的R循环。

      说实话,我有点惊讶Rcpp能够比R等同物快2倍。

相关问题