gpt4 book ai didi

c++ - 根据 Rcpp.h 为自定义类扩展 Rcpp::as

转载 作者:行者123 更新时间:2023-12-04 03:35:01 28 4
gpt4 key购买 nike

我正在研究一个同时使用 Rcpp::IntegerVector (行/列指针)和模板化 std::vector<T> 的 Rcpp 稀疏矩阵类。基本原理是,在极大的稀疏矩阵中深度复制整数指针 vector (@i@p)的开销可以通过简单地将它们保留为 R 对象的指针来避免,并且一致地,微基准测试表明这种方法几乎正好占了一半在使用较少内存的情况下转换为 Eigen::SparseMatrix<T>arma::SpMat<T> 的时间。
准系统 Rcpp 稀疏矩阵类

namespace SpRcpp {

template<typename T>
class SpMatrix {

public:
Rcpp::IntegerVector i, p;
std::vector<T> x;
unsigned int n_row, n_col;

// constructor for the class from an Rcpp::S4 object
SpMatrix(Rcpp::S4& mat) {
Rcpp::IntegerVector dims = mat.slot("Dim");
n_row = (unsigned int)dims[0];
i = mat.slot("i");
p = mat.slot("p");
x = Rcpp::as<std::vector<T>>(mat.slot("x"));
};
// other constructors, class methods, iterators, etc.
};
}
示例用法:
//[[Rcpp::export]]
std::vector<float> SpRcpp_SpMatrix(Rcpp::S4& mat) {
SpRcpp::SpMatrix<float> A(mat);
return A.x;
}
这行得通!
但是,我想让 Rcpp 隐式地将 S4 dgCMatrix 对象转换为 SpRcpp::SpMatrix 对象,以启用如下功能:
隐式 Rcpp 包装
//[[Rcpp::export]]
std::vector<float> SpRcpp_SpMatrix2(SpRcpp::SpMatrix<float>& mat) {
return mat.x;
}
这就是使用 Rcpp::as 的情况。
我尝试了以下方法:
namespace Rcpp {
namespace traits {
template <typename T>
class Exporter< SpRcpp::SpMatrix<T> > {
public:
Exporter(SEXP x) { Rcpp::S4 mat = x; }
SpRcpp::SpMatrix<T> get() {
return SpRcpp::SpMatrix<T>(mat);
}
private: Rcpp::S4 mat;
};
}
}
这可以编译,我知道 SpRcpp::SpMatrix<T>(Rcpp::S4& x) 构造函数可以工作,但是当我尝试将 dgCMatrix 输入 SpRcpp_SpMatrix() 时,我得到了错误: Error in SpRcpp_SpMatrix2(A) : Not an S4 object.我认为这是因为我在所有类声明之前声明了以下内容:
#include <RcppCommon.h>
#include <Rcpp.h>
根据文档 hereRcppGallery exampleRcppArmadillo 实现, #include <Rcpp.h> 不能在 Rcpp::asRcpp::wrap 函数之前,但在我的情况下,我不能这样做,因为我的类定义需要 Rcpp.h
问题:Rcpp::as 类依赖于 SpRcpp::SpMatrix 时,如何从 Rcpp::S4 dgCMatrix 为 SpMatrix 创建 Rcpp.h

最佳答案

创建一个 Rcpp SparseMatrix 类实际上非常简单!我想多了。

#include <rcpp.h>

// Rcpp for sparse matrices (spRcpp)
namespace Rcpp {
class SparseMatrix {
public:
Rcpp::IntegerVector i, p;
Rcpp::NumericVector x;
int n_rows, n_cols;

// constructor
SparseMatrix(Rcpp::S4 mat) {
Rcpp::IntegerVector dim = mat.slot("Dim");
i = mat.slot("i");
p = mat.slot("p");
x = mat.slot("x");
n_rows = (int)dim[0];
n_cols = (int)dim[1];
};
};
}

namespace Rcpp {
template <> Rcpp::SparseMatrix as(SEXP mat) {
return Rcpp::SparseMatrix(mat);
}
}

//[[Rcpp::export]]
Rcpp::NumericVector toRcppSparseMatrix(Rcpp::SparseMatrix& A) {
return A.x;
}
给定一个 Matrix::dgCMatrix , mat , 调用 toRcppSparseMatrix(mat)对于 2500 万个值,在 1-2 微秒内返回非零值。这与 RcppArmadillo 或 RcppEigen 稀疏矩阵转换形成对比,后者对于相同的矩阵需要大约 250 毫秒并在内存中运行深度复制。
正如 Dirk 建议的那样,使用 RcppArmadillo ivecdvec非常高效,但仍然创建了浅拷贝,导致运行时间约为 100 毫秒并消耗了一些内存。
显然,上述方法仅限于 double 类型,因此如果没有深拷贝,浮点操作是不可能的。

关于c++ - 根据 Rcpp.h 为自定义类扩展 Rcpp::as,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67091344/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com