Rcpp可以用来加速其他R函数的调用吗?

问题描述 投票:0回答:2

我正在编写一个用于统计分析和机器学习 (ML) 的 R 包,该包通常非常慢。它很慢,因为它涉及训练和预测模型,包括统计和机器学习。我的包与模型无关,我的意思是它与 R 中的任何其他模型训练和预测包接口,以重新训练他们的模型并使用他们的模型进行预测。经过广泛的分析和代码重构(主要是通过尽可能多地转换为向量化和矩阵运算),我发现无法通过重构进一步加快速度的慢点归结为代码:

  • 从其他 R 包调用预测函数。我的主要程序可能会调用预测函数数千次,因此即使需要 0.1 秒的预测函数也可能导致我的函数需要花费几分钟甚至几个小时才能运行。
  • 从其他 R 包调用训练模型。我的一些程序将输入模型重新训练 100 到 1000 次。因此,1 秒的模型训练时间大约需要 17 分钟才能运行。比这更慢的训练时间变得非常难以管理。

我想知道 Rcpp 是否可以帮助加快我的情况。请注意我在这里没有问什么:

  • 我并不是在问我是否真的需要多次运行和预测模型。我正在单独探讨这个重要问题;我确实在努力尽可能地减少这些需求。所以,我问这个问题是基于这样的假设:我确实需要经常运行模型和预测。
  • 我当然打算实现并行处理来帮助缓解这个问题,但这只是一个有限的解决方案。即使某些用户拥有多达 10 个物理计算机核心(很少有用户拥有),将我上面给出的示例速度除以 10 仍然会导致代码缓慢。我正在尝试走得更远。并行处理将是我能做的任何其他事情的额外解决方案。

我对 Rcpp 是否有帮助的主要疑问是,最慢的代码是当我调用其他包的 R 函数时。我已经阅读了很多关于 Rcpp 的内容,我什至正在参加 DataCamp 课程主题。然而,从我目前对 Rcpp 的探索来看,尽管许多资料解释了为什么我们要使用 Rcpp(以加速缓慢的 R 代码),但我无法找到任何资料来清楚地说明 Rcpp 无法帮助解决哪些问题.

据我所知,Rcpp 在调用 R 函数时无法提供任何加速。减慢我的代码速度的函数是由其他包编写的函数。例如,我有 一篇文章演示了我的包功能,分别使用

nnet::nnet()
nnet::predict.nnet()
来训练和预测神经网络,以及
gbm::gbm()
gbm::predict.gbm()
分别训练和预测梯度增强机。有没有办法利用Rcpp来优化这些函数的调用?

如果我可以实时调用

Rcpp::cppFunction()
来接收这些函数,将它们编译为C++,然后继续用我的程序执行它们,那么这可能是一个可行的解决方案。但是使用Rcpp可以吗?我将不胜感激这里的任何指导。我愿意接受一个明确解释的答案:“不,Rcpp 无法帮助您解决问题,原因如下。”

r algorithm optimization rcpp
2个回答
5
投票

根据 Dirk Eddelbuettel(Rcpp 的创建者)所著的文章“从 C++ 调用 R 函数”

调用函数[…]很慢,因为涉及开销。从 C++ 代码内部重复调用它(可能隐藏在多个循环中)是非常愚蠢的。这必须比等效的 C++ 代码慢,甚至比 R 代码慢(因为数据的编组)。

那篇文章已有十一年了,但我认为从那时起情况没有改变。


0
投票

这里似乎有些方面被混淆了:

  • R 代码以 R 代码的速度作为 R 代码运行,即使从 Rcpp 调用也是如此。 R 没有任何神奇的改变可以实现改变R 解释器
  • C++ 代码以编译代码的速度运行,通常更快,有时快很多
  • 可以混合搭配:C++代码可以通过例如
    Rcpp::Function
    调用R代码。据记录,这在很早的时候曾经有更多令人望而却步的开销(这就是前面的答案所指的),但几年前变得(好多了!)更好(请参阅发布新闻或变更日志)。仍然有一些开销,但它是完全可行的,并且有许多包用于 some 任务(包括 Rcpp 本身)。
  • 人们通常不想重复调用
    cppFunction()
    ,或者在包的每次开始时调用:当 Rcpp 代码有帮助时,将其包装在包中是很简单的。
  • 也可以混合搭配,有一些包将编译后的函数传递给 R 函数。

最重要的是,遵循一般规则通常是有回报的:不要猜测,而是进行分析和测量。

© www.soinside.com 2019 - 2024. All rights reserved.