C++ 是否可以将矩阵列表传递给vector<;本征::映射<;特征::矩阵xD>&燃气轮机;内联的?
我试图以列表格式对矩阵行执行操作,以计算我正在编写的某些软件的Hessian矩阵(混合偏导数矩阵)的部分。我发现我只能在R中这么快地完成这项工作(即使是并行化),因此我已经切换到Rcpp以获得更快的速度,并切换到RcppEigen以获得提供的高级矩阵操作。当我依赖列表类型来表示从R传递来的矩阵/向量列表时,我的Cpp代码会随着列表长度(每个元素都是矩阵或向量)的增加而大大降低。我不知道确切的原因,但这可能是因为动态大小的对象?我的问题是:我是否可以使用RcppEigen通过如下方式将列表从R传递到标准模板库(STL)的向量容器中C++ 是否可以将矩阵列表传递给vector<;本征::映射<;特征::矩阵xD>&燃气轮机;内联的?,c++,r,vector,stl,rcpp,C++,R,Vector,Stl,Rcpp,我试图以列表格式对矩阵行执行操作,以计算我正在编写的某些软件的Hessian矩阵(混合偏导数矩阵)的部分。我发现我只能在R中这么快地完成这项工作(即使是并行化),因此我已经切换到Rcpp以获得更快的速度,并切换到RcppEigen以获得提供的高级矩阵操作。当我依赖列表类型来表示从R传递来的矩阵/向量列表时,我的Cpp代码会随着列表长度(每个元素都是矩阵或向量)的增加而大大降低。我不知道确切的原因,但这可能是因为动态大小的对象?我的问题是:我是否可以使用RcppEigen通过如下方式将列表从R传递
vector<Eigen::Map<Eigen::MatrixXd>> A(as<vector<Eigen::Map<Eigen::MatrixXd>> >(AA))
向量A(as(AA))
我之所以想这样做,是因为我读到访问向量比访问列表快得多。然而,我可能误解了这一点,如果是这样,我道歉
其思想是传入向量列表(B2)和矩阵列表(A2)。在这些列表的每个索引中,我迭代当前索引A2中的矩阵(A)行和当前索引B2中的向量(b),计算:
b[j]*t(A[j,])%*%A[j,]
对于j,从0到第1行。我将得到一个列表,其大小等于该索引中矩阵的行数,然后转到外部限制的下一个索引,以此类推
下面是一个可复制的示例,说明了我可以使用列表执行的操作:
library(inline)
library(RcppEigen)
library(microbenchmark)
## Create function which takes list into Rcpp and does all manipulations internally (no lapply outside)
A2 <- lapply(1:2, function(t) matrix(rnorm(10 * t), nrow = t, ncol = 10))
B2 <- lapply(1:2, function(t) rnorm(t))
## This becomes slower relative to R as the size increases.
## Something is not right in how I am programming this.
retLLMat <- "using Eigen::VectorXd;
typedef Eigen::Map<Eigen::MatrixXd> MapMatd;
typedef Eigen::Map<Eigen::VectorXd> MapVecd;
List A(AA), B(BB);
int listSize = A.size(), ncol, sublistSize;
List outList;
double sub;
for (int i = 0; i < listSize; i++)
{
List subList;
MapMatd subMat(as<MapMatd >(A[i]));
MapVecd subVec(as<MapVecd >(B[i]));
ncol = subMat.cols();
VectorXd currRow(ncol);
sublistSize = subMat.rows();
for (int j = 0; j < sublistSize; j++)
{
currRow = subMat.row(j);
sub = subVec[j];
subList[String(j)] = (sub * currRow) * currRow.transpose();
}
outList[String(i)] = subList;
}
return wrap(outList);"
## Compile Cpp code
retLLMatC <- cxxfunction(signature(AA = "List", BB = "List"), retLLMat, plugin = "RcppEigen")
## R version
retLLMat <- function(A, B) mapply(function(a, b) mapply(function(a, b) b * a, lapply(apply(a, 1, function(t) list(tcrossprod(t))), "[[", 1), b, SIMPLIFY = FALSE), A, B, SIMPLIFY = FALSE)
## Test R vs Rcpp version
microbenchmark(retLLMat(A2, B2), retLLMatC(A2, B2))
库(内联)
图书馆(RcppEigen)
图书馆(微基准)
##创建将列表纳入Rcpp并在内部执行所有操作的函数(外部无重叠)
A2你可以用另一种方法来做:使用一个标准的列表(我们知道它是通过的),其中每个元素(无论如何必须是SEXP
)通过一个本征映射(我们也知道单独通过)
所以我会从简单开始,一步一步地让它变得更复杂,直到它崩溃。嗨,德克!首先,我已经阅读了你们的文章和例子有一段时间了,所以我在这里有点震惊。很酷,你还是有时间在堆栈上响应!我将编辑我答案的底部,以显示我认为这是什么样子。我仍然有一个小问题,我认为我已经用迭代器解决了,但是,取消引用意味着类型丢失,或者类似的东西,我相信。
vector<Eigen::Map<Eigen::MatrixXd>>
## Testing using a vector of Map<MatrixXd>
## Simplified by trying to return the list after reading it in
VectorMat <- "using Eigen::MatrixXd;
using std::vector;
typedef Eigen::Map<Eigen::MatrixXd> MapMatd;
vector<MapMatd> A(as<vector<MapMatd> >(AA);
return wrap(A);"
## This produces errors
test <- cxxfunction(signature(AA = "List"), VectorMat, plugin = "RcppEigen")
ListMat1 <- "using Eigen::MatrixXd;
typedef Eigen::Map<Eigen::MatrixXd> MapMatd;
ListOf<MapMatd> A(as<ListOf<MapMatd> >(AA));
return wrap(A);"
ListMat <- cxxfunction(signature(AA = "List"), ListMat1, plugin = "RcppEigen")
res <- ListMat(A2)
b2 <- lapply(1:5, function(t) numeric(t))
vecTest <- "ListOf<NumericVector> b(as<ListOf<NumericVector> >(bb));
NumericVector res = b[0];
return wrap(res);"
vecTestfn <- cxxfunction(signature(bb = "List"), vecTest, plugin = "RcppEigen")
vecTestfn(b2)
ListMatInd <- "using Eigen::MatrixXd;
typedef Eigen::Map<Eigen::MatrixXd> MapMatd;
ListOf<MapMatd> A(as<ListOf<MapMatd> >(AA));
MatrixXd res = A[0];
return wrap(res);"
ListMatIndfn <- cxxfunction(signature(AA = "List"), ListMatInd, plugin = "RcppEigen")