Rcpp Eigen原地矩阵乘法错误

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

Rcpp Eigen inplace matrix multiplication error

问题

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

SEXP cpp_hom_crit(
	const Eigen::Map<Eigen::MatrixXd> Q, Eigen::Map<Eigen::VectorXd> d, Eigen::Map<Eigen::MatrixXd> Qinv) {

    Q *= d.asDiagonal() * Qinv; //错误发生在这里

    return Rcpp::wrap(Q);
}

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

SEXP cpp_hom_crit(
	const Eigen::Map<Eigen::MatrixXd> Q, Eigen::Map<Eigen::VectorXd> d, Eigen::Map<Eigen::MatrixXd> Qinv) {

    Q = Q * d.asDiagonal() * Qinv; //错误发生在这里

    return Rcpp::wrap(Q);
}

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

英文:

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.

SEXP cpp_hom_crit(
	const Eigen::Map&lt;Eigen::MatrixXd&gt; Q, Eigen::Map&lt;Eigen::VectorXd&gt; d, Eigen::Map&lt;Eigen::MatrixXd&gt; Qinv) {

    Q *= d.asDiagonal() * Qinv; //error happens here

    return Rcpp::wrap(Q);
}

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

SEXP cpp_hom_crit(
	const Eigen::Map&lt;Eigen::MatrixXd&gt; Q, Eigen::Map&lt;Eigen::VectorXd&gt; d, Eigen::Map&lt;Eigen::MatrixXd&gt; Qinv) {

    Q = Q * d.asDiagonal() * Qinv; //error happens here

    return Rcpp::wrap(Q);
}

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

答案1

得分: 2

以下是已翻译的部分:

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

代码

#include <RcppEigen.h>

// [[Rcpp::depends(RcppEigen)]]

// [[Rcpp::export]]
Eigen::MatrixXd cpp_hom_crit(const Eigen::Map<Eigen::MatrixXd> Q,
                             const Eigen::Map<Eigen::VectorXd> d,
                             const Eigen::Map<Eigen::MatrixXd> Qinv) {

    auto res = Q * d.asDiagonal() * Qinv;
    return res;
}

/*** R
v <- as.numeric(1:3)
M <- v %*% t(v)
Mi <- chol2inv(M)
cpp_hom_crit(M, v, Mi)
*/

输出

> Rcpp::sourceCpp("~/git/stackoverflow/76625654/answer.cpp")

> v <- as.numeric(1:3)

> M <- v %*% t(v)

> Mi <- chol2inv(M)

> cpp_hom_crit(M, v, Mi)
     [,1]      [,2]      [,3]
[1,] 0.75 0.0694444 0.0370370
[2,] 1.50 0.1388889 0.0740741
[3,] 2.25 0.2083333 0.1111111
>

这些值当然是毫无意义的,但它们至少说明了正确的维度。请注意,像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

#include &lt;RcppEigen.h&gt;

// [[Rcpp::depends(RcppEigen)]]

// [[Rcpp::export]]
Eigen::MatrixXd cpp_hom_crit(const Eigen::Map&lt;Eigen::MatrixXd&gt; Q,
                             const Eigen::Map&lt;Eigen::VectorXd&gt; d,
                             const Eigen::Map&lt;Eigen::MatrixXd&gt; Qinv) {

    auto res = Q * d.asDiagonal() * Qinv;
    return res;
}

/*** R
v &lt;- as.numeric(1:3)
M &lt;- v %*% t(v)
Mi &lt;- chol2inv(M)
cpp_hom_crit(M, v, Mi)
*/

Output

&gt; Rcpp::sourceCpp(&quot;~/git/stackoverflow/76625654/answer.cpp&quot;)

&gt; v &lt;- as.numeric(1:3)

&gt; M &lt;- v %*% t(v)

&gt; Mi &lt;- chol2inv(M)

&gt; cpp_hom_crit(M, v, Mi)
     [,1]      [,2]      [,3]
[1,] 0.75 0.0694444 0.0370370
[2,] 1.50 0.1388889 0.0740741
[3,] 2.25 0.2083333 0.1111111
&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:

确定