C ++用于算术运算的性能不佳

时间:2018-08-04 11:55:15

标签: r performance rcpp

我仅使用R和c ++(使用rcpp)中的算术运算编写了一个非常简单的函数。比较这两个函数可以发现,我的c ++实现比我的R代码要慢得多,这让我很困惑。

c ++版本:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector dn_cpp(NumericVector x, NumericVector sigma, NumericVector mu) {
  return   1/(sqrt(2*M_PI)*sigma) * exp(pow((x-mu),2)/(-2*pow(sigma, 2)) );
}

R版本:

dn_r <- function(x, sigma, mu) {
  1/(sqrt(2*pi)*sigma) * exp((x-mu)^2/(-2*sigma^2)  )
}

比较两者:

library(microbenchmark)
microbenchmark(
  dn_r(1,1,1),
  dn_cpp(1,1,1),
  times = 10000
)

# Unit: nanoseconds
#             expr  min   lq      mean median     uq     max neval
#    dn_r(1, 1, 1)  509  567  667.1547    627  715.5   12690 10000
#  dn_cpp(1, 1, 1) 1094 1242 1713.8351   1335 1479.0 3192711 10000

有人可以解释为什么我的c ++函数缺乏性能吗?

1 个答案:

答案 0 :(得分:6)

和往常一样,李哲源Dirk Eddelbuettel是完全正确的;对于这些类型的操作,绝对没有理由期望C ++版本比使用函数调用的数据的R版本更快。我添加此答案仅是为了展示李哲源的建议:

microbenchmark(
    dn_r(1,1,1),
    dn_cpp(1,1,1),
    times = 10000
)

Unit: microseconds
            expr   min    lq      mean median    uq       max neval
   dn_r(1, 1, 1) 4.061 4.390  7.569112  4.869 5.175 26308.271 10000
 dn_cpp(1, 1, 1) 8.362 9.025 12.148559  9.265 9.653  5834.242 10000

microbenchmark(
    dn_r(rnorm(1e3), 1, 1),
    dn_cpp(rnorm(1e3), 1, 1),
    times = 10000
) 

Unit: microseconds
                      expr     min      lq     mean  median       uq      max
   dn_r(rnorm(1000), 1, 1) 298.134 303.631 313.9681 305.453 308.7080 4111.497
 dn_cpp(rnorm(1000), 1, 1) 199.949 205.571 214.6522 207.414 210.5015 3859.939

microbenchmark(
    dn_r(rnorm(1e5), 1, 1),
    dn_cpp(rnorm(1e5), 1, 1),
    times = 10000
) 

Unit: milliseconds
                       expr      min       lq     mean   median       uq      max
   dn_r(rnorm(1e+05), 1, 1) 28.60395 29.28238 30.85371 29.46879 29.95939 160.0769
 dn_cpp(rnorm(1e+05), 1, 1) 18.89528 19.44148 20.10618 19.60433 19.75410 143.7250

对于较短的向量,额外的开销意味着R版本会更快,而对于较长的向量,您可以获得一些性能提升。