Rcpp Eigen原地矩阵乘法错误

huangapple go评论87阅读模式
英文:

Rcpp Eigen inplace matrix multiplication error

问题

我是新手学习Rcpp和Eigen,尝试运行一个原地矩阵乘法时,遇到了这个错误。R没有告诉我错误的具体信息。

  1. SEXP cpp_hom_crit(
  2. const Eigen::Map<Eigen::MatrixXd> Q, Eigen::Map<Eigen::VectorXd> d, Eigen::Map<Eigen::MatrixXd> Qinv) {
  3. Q *= d.asDiagonal() * Qinv; //错误发生在这里
  4. return Rcpp::wrap(Q);
  5. }

我也尝试了这个,但也不起作用

  1. SEXP cpp_hom_crit(
  2. const Eigen::Map<Eigen::MatrixXd> Q, Eigen::Map<Eigen::VectorXd> d, Eigen::Map<Eigen::MatrixXd> Qinv) {
  3. Q = Q * d.asDiagonal() * Qinv; //错误发生在这里
  4. return Rcpp::wrap(Q);
  5. }

如何解决这个错误,可能让它运行更快?

英文:

I'm new to Rcpp and Eigen and I'm trying to run a inplace matrix multiplication while I run into this error. R didn't tell me what the error is about.

  1. SEXP cpp_hom_crit(
  2. const Eigen::Map&lt;Eigen::MatrixXd&gt; Q, Eigen::Map&lt;Eigen::VectorXd&gt; d, Eigen::Map&lt;Eigen::MatrixXd&gt; Qinv) {
  3. Q *= d.asDiagonal() * Qinv; //error happens here
  4. return Rcpp::wrap(Q);
  5. }

I tried this one also, but it does not work either

  1. SEXP cpp_hom_crit(
  2. const Eigen::Map&lt;Eigen::MatrixXd&gt; Q, Eigen::Map&lt;Eigen::VectorXd&gt; d, Eigen::Map&lt;Eigen::MatrixXd&gt; Qinv) {
  3. Q = Q * d.asDiagonal() * Qinv; //error happens here
  4. return Rcpp::wrap(Q);
  5. }

How can I resolve this error and possibly make this faster?

答案1

得分: 2

以下是已翻译的部分:

这是解决您的问题的一种方法。正如评论中@chtz所提到的,您不能声明一个变量为const然后赋值给它。因此,在这里我们赋值给一个新的临时变量,然后返回该结果。

代码

  1. #include <RcppEigen.h>
  2. // [[Rcpp::depends(RcppEigen)]]
  3. // [[Rcpp::export]]
  4. Eigen::MatrixXd cpp_hom_crit(const Eigen::Map<Eigen::MatrixXd> Q,
  5. const Eigen::Map<Eigen::VectorXd> d,
  6. const Eigen::Map<Eigen::MatrixXd> Qinv) {
  7. auto res = Q * d.asDiagonal() * Qinv;
  8. return res;
  9. }
  10. /*** R
  11. v <- as.numeric(1:3)
  12. M <- v %*% t(v)
  13. Mi <- chol2inv(M)
  14. cpp_hom_crit(M, v, Mi)
  15. */

输出

  1. > Rcpp::sourceCpp("~/git/stackoverflow/76625654/answer.cpp")
  2. > v <- as.numeric(1:3)
  3. > M <- v %*% t(v)
  4. > Mi <- chol2inv(M)
  5. > cpp_hom_crit(M, v, Mi)
  6. [,1] [,2] [,3]
  7. [1,] 0.75 0.0694444 0.0370370
  8. [2,] 1.50 0.1388889 0.0740741
  9. [3,] 2.25 0.2083333 0.1111111
  10. >

这些值当然是毫无意义的,但它们至少说明了正确的维度。请注意,像LAPACK这样的库通常有专门用于常见的矢量-矩阵乘积表达式的函数,内部进行循环操作,可能还会避免临时变量,因此不清楚Eigen是否会自动更快(多)。

英文:

Here is one way to fix your problem. As @chtz alluded to in the comment, you cannot declare a variable const and assign to it. So here we assign to a new temporary variable and return that result.

Code

  1. #include &lt;RcppEigen.h&gt;
  2. // [[Rcpp::depends(RcppEigen)]]
  3. // [[Rcpp::export]]
  4. Eigen::MatrixXd cpp_hom_crit(const Eigen::Map&lt;Eigen::MatrixXd&gt; Q,
  5. const Eigen::Map&lt;Eigen::VectorXd&gt; d,
  6. const Eigen::Map&lt;Eigen::MatrixXd&gt; Qinv) {
  7. auto res = Q * d.asDiagonal() * Qinv;
  8. return res;
  9. }
  10. /*** R
  11. v &lt;- as.numeric(1:3)
  12. M &lt;- v %*% t(v)
  13. Mi &lt;- chol2inv(M)
  14. cpp_hom_crit(M, v, Mi)
  15. */

Output

  1. &gt; Rcpp::sourceCpp(&quot;~/git/stackoverflow/76625654/answer.cpp&quot;)
  2. &gt; v &lt;- as.numeric(1:3)
  3. &gt; M &lt;- v %*% t(v)
  4. &gt; Mi &lt;- chol2inv(M)
  5. &gt; cpp_hom_crit(M, v, Mi)
  6. [,1] [,2] [,3]
  7. [1,] 0.75 0.0694444 0.0370370
  8. [2,] 1.50 0.1388889 0.0740741
  9. [3,] 2.25 0.2083333 0.1111111
  10. &gt;

The values are of course nonsensical but they illustrate at least the correct dimension. Note that libraries like LAPACK often have dedicated functions for common vector-matrix product expressions, do the looping internally and may also avoid the temporary so not it is not clear that Eigen will automatically be (much) faster.

huangapple
  • 本文由 发表于 2023年7月6日 13:05:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76625654.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定