Rcpp/RcppArmadillo C++/R 性能平衡
Rcpp/RcppArmadillo C++/R balance for Performance
当我对用 RcppArmadillo 编写的 code/functions 的小块进行基准测试时,我有时会看到令人难以置信的(对于简单操作中的嵌套 for 循环,55 倍与 R 相比)到适度(对于持续时间较长的函数,1.3 倍与 R 相比)速度提升。对此印象深刻,我决定翻译大约 400 行代码来创建一个 C++ 函数(带有一些小的相邻 C++ 函数)来替换我的 R 应用程序的计算密集型主体。
旧结果:
RcppArmadillo 代码比原生 R 慢 运行 ~3 倍(更新 - 可能是一个糟糕的基准 - 正在处理它)。代码的混合 RcppArmadillo 和 R 变体比 R 快 运行 ~1.10 倍。
Update/Lessons 了解到:
C++ 密集型代码比 R&C++ 混合代码快 运行 ~6 倍。对于任何路人来说,我犯的错误如下:
- 我没有在我的 R 基准测试中考虑变量实例化(不公平的比较)。
- 在嵌套的 C++ 循环中错放了一些计算。在 R 变体中,它们在所述循环之外(包括大 FFT 等)。人为错误。
- 正在传递大量函数参数(大向量、矩阵、转换等)。通过移植更多代码解决了这个问题。
- 我没有有效地处理内存。正在制作额外的副本,而不仅仅是使用它们。这些副本有助于提高可读性,但可能会损害性能。易于修复。
- 使用全局变量来减少函数传递的开销,并从一些计算中删除一些大的临时向量(向量大小:2^15)。
编辑(对于第一条评论的不连续之处,我们深表歉意post)
旧问题:
- 是否建议在 RcppArmadillo 代码 space 中全局变量 instantiation/preliminary 内存分配,以节省函数 body/R 垃圾收集中的许多变量声明?或者 Rcpp 是否像 R 一样及时地处理这些问题?
- 我假设 Rcpp 由于与 R 接口(保护变量、垃圾收集等)而损失了一些性能,我是否正确?如果是这样,我在哪里可以找到处理这些操作的代码(文件名)/文档,以便我可以学习如何更好地使用它。
任何实用的建议表示赞赏。对于这个含糊的问题,我深表歉意,我是 SO 的新手,RcppArmadillo 包的新手,并且已经 10 年没有编写 C++ 了。
The RcppArmadillo code is running ~3x slower then native R. A hybrid RcppArmadillo & R variant of the code is running ~1.10 times faster then R.
你肯定抄了很多。这根本不合理。也许是时候分析您的代码了?
以任何发布的例子为例。也许来自有多个帖子的 Rcpp Gallery。也许从现在开始有 250 (!!) 个使用 RcppArmadillo 的 CRAN 包。从简单的事情开始,然后计时。
您应该看到从 R 转换为 C++ 的循环的 ~ 50x 因子。对于纯矢量化代码,您应该会发现速度快了近 1.5 倍(因为 R 倾向于对我们在小扩展中编写的代码进行更多错误检查)。
编辑:这是一个简单基准测试,显示设置一个基准是多么简单。您确实可以(并且应该!!)为您怀疑效率低下的所有部分计时。我们都会犯错误,无论是在设计中还是在执行中。好处是您同时拥有 和 两种工具,大量已发布的示例可以指导您。
R> Rfunc <- function(N) { s <- 0; for (i in 1:N) for (j in 1:N) s <- s+1; s }
R> Rfunc(10)
[1] 100
R>
R> library(Rcpp)
R> cppFunction("double Cppfunc(int N) { double s=0; for (int i=0; i<N; i++) for (int j=0; j<N; j++) s++; return(s); }")
R> Cppfunc(10)
[1] 100
R>
R> library(rbenchmark)
R> N <- 1000
R> benchmark(Rfunc(N), Cppfunc(N), order="relative")[,1:4]
test replications elapsed relative
2 Cppfunc(N) 100 0.073 1.000
1 Rfunc(N) 100 12.596 172.548
R>
当我对用 RcppArmadillo 编写的 code/functions 的小块进行基准测试时,我有时会看到令人难以置信的(对于简单操作中的嵌套 for 循环,55 倍与 R 相比)到适度(对于持续时间较长的函数,1.3 倍与 R 相比)速度提升。对此印象深刻,我决定翻译大约 400 行代码来创建一个 C++ 函数(带有一些小的相邻 C++ 函数)来替换我的 R 应用程序的计算密集型主体。
旧结果: RcppArmadillo 代码比原生 R 慢 运行 ~3 倍(更新 - 可能是一个糟糕的基准 - 正在处理它)。代码的混合 RcppArmadillo 和 R 变体比 R 快 运行 ~1.10 倍。
Update/Lessons 了解到: C++ 密集型代码比 R&C++ 混合代码快 运行 ~6 倍。对于任何路人来说,我犯的错误如下:
- 我没有在我的 R 基准测试中考虑变量实例化(不公平的比较)。
- 在嵌套的 C++ 循环中错放了一些计算。在 R 变体中,它们在所述循环之外(包括大 FFT 等)。人为错误。
- 正在传递大量函数参数(大向量、矩阵、转换等)。通过移植更多代码解决了这个问题。
- 我没有有效地处理内存。正在制作额外的副本,而不仅仅是使用它们。这些副本有助于提高可读性,但可能会损害性能。易于修复。
- 使用全局变量来减少函数传递的开销,并从一些计算中删除一些大的临时向量(向量大小:2^15)。
编辑(对于第一条评论的不连续之处,我们深表歉意post) 旧问题:
- 是否建议在 RcppArmadillo 代码 space 中全局变量 instantiation/preliminary 内存分配,以节省函数 body/R 垃圾收集中的许多变量声明?或者 Rcpp 是否像 R 一样及时地处理这些问题?
- 我假设 Rcpp 由于与 R 接口(保护变量、垃圾收集等)而损失了一些性能,我是否正确?如果是这样,我在哪里可以找到处理这些操作的代码(文件名)/文档,以便我可以学习如何更好地使用它。
任何实用的建议表示赞赏。对于这个含糊的问题,我深表歉意,我是 SO 的新手,RcppArmadillo 包的新手,并且已经 10 年没有编写 C++ 了。
The RcppArmadillo code is running ~3x slower then native R. A hybrid RcppArmadillo & R variant of the code is running ~1.10 times faster then R.
你肯定抄了很多。这根本不合理。也许是时候分析您的代码了?
以任何发布的例子为例。也许来自有多个帖子的 Rcpp Gallery。也许从现在开始有 250 (!!) 个使用 RcppArmadillo 的 CRAN 包。从简单的事情开始,然后计时。
您应该看到从 R 转换为 C++ 的循环的 ~ 50x 因子。对于纯矢量化代码,您应该会发现速度快了近 1.5 倍(因为 R 倾向于对我们在小扩展中编写的代码进行更多错误检查)。
编辑:这是一个简单基准测试,显示设置一个基准是多么简单。您确实可以(并且应该!!)为您怀疑效率低下的所有部分计时。我们都会犯错误,无论是在设计中还是在执行中。好处是您同时拥有 和 两种工具,大量已发布的示例可以指导您。
R> Rfunc <- function(N) { s <- 0; for (i in 1:N) for (j in 1:N) s <- s+1; s }
R> Rfunc(10)
[1] 100
R>
R> library(Rcpp)
R> cppFunction("double Cppfunc(int N) { double s=0; for (int i=0; i<N; i++) for (int j=0; j<N; j++) s++; return(s); }")
R> Cppfunc(10)
[1] 100
R>
R> library(rbenchmark)
R> N <- 1000
R> benchmark(Rfunc(N), Cppfunc(N), order="relative")[,1:4]
test replications elapsed relative
2 Cppfunc(N) 100 0.073 1.000
1 Rfunc(N) 100 12.596 172.548
R>