我正在开发一个应用程序,经常计算正则化不完全贝塔函数。该应用程序使用C++编写,并调用
因此,我转向了
在R中,我们通过对随机数调用函数300000次来测量速度。
为了复现这个例子,需要安装R和包
我认为这可能与在
谢谢!
FYI,
相比之下,Boost声称“这个实现是基于1992年DiDonato和Morris在ACM上发表的《算法708:不完全贝塔函数比率的有效数字计算》。”(
R::pbeta()
。当我尝试将应用程序多线程化时,一些来自R::pbeta()
的警告消息导致堆栈溢出。因此,我转向了
boost::math::ibeta()
。一切都很顺利,直到我测量速度为止。下面的C++文件whyIsBoostSlower.cpp
使用R::pbeta()
或boost::math::ibeta()
实现了正则化不完全贝塔函数。// [[Rcpp::plugins(cpp17)]]
#include <boost/math/special_functions/beta.hpp>
// [[Rcpp::depends(BH)]]
#include <Rcpp.h>
using namespace Rcpp;
// Compute the regularized incomplete Beta function.
// [[Rcpp::export]]
NumericVector RIBF(NumericVector q, NumericVector a, NumericVector b,
bool useboost = false)
{
NumericVector rst(q.size());
for (int i = 0, iend = q.size(); i < iend; ++i)
{
if (useboost) rst[i] = boost::math::ibeta( a[i], b[i], q[i] );
else rst[i] = R::pbeta( q[i], a[i], b[i], 1, 0 );
}
return rst;
}
在R中,我们通过对随机数调用函数300000次来测量速度。
Rcpp::sourceCpp("whyIsBoostSlower.cpp")
set.seed(123)
N = 300000L
q = runif(N) # Generate quantiles.
a = runif(N, 0, 10) # Generate a in (0, 10)
b = runif(N, 0, 10) # Generate b in (0, 10)
# Use R's pbeta(). This function calls a C wrapper of toms708.c:
# https://svn.r-project.org/R/trunk/src/nmath/toms708.c
system.time({ Rrst = RIBF(q, a, b, useboost = F) })
# Windows 10 (seconds):
# user system elapsed
# 0.11 0.00 0.11
# RedHat Linux:
# user system elapsed
# 0.097 0.000 0.097
# Use Boost's implementation, which also depends on TOMS 708 by their claim:
# https://www.boost.org/doc/libs/1_41_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_beta/ibeta_function.html
system.time({ boostRst = RIBF(q, a, b, useboost = T) })
# Windows 10:
# user system elapsed
# 0.52 0.00 0.52
# RedHat Linux:
# user system elapsed
# 0.988 0.001 0.993
range(Rrst - boostRst)
# -1.221245e-15 1.165734e-15
为了复现这个例子,需要安装R和包
Rcpp
。在Windows上,还需要安装包含GCC分发的Rtools
。优化标志默认为-O2
。
R::pbeta()
和boost::math::ibeta()
都基于ACM TOMS 708,但是boost::math::ibeta()
在Windows上慢5倍,在Linux上慢10倍。我认为这可能与在
boost::math::ibeta()
中设置Policy
参数有关,但是如何设置呢?谢谢!
FYI,
R::pbeta()
在R-4.2.3/src/nmath/pbeta.c
中定义。 R::pbeta()
调用了bratio()
,该函数在R-4.2.3/src/nmath/toms708.c
中定义,即https://svn.r-project.org/R/trunk/src/nmath/toms708.c。其中的代码是TOMS 708 Fortran代码的C翻译版本。这个翻译是由R的核心团队完成的。相比之下,Boost声称“这个实现是基于1992年DiDonato和Morris在ACM上发表的《算法708:不完全贝塔函数比率的有效数字计算》。”(
boost::math::ibeta()
)
Rcpp
标签相关的问题(尽管我努力获取无意义的问题或重复的问题并进行删除)。还有一些与Boost和R的BH包交集的问题。 - Dirk Eddelbuettel