如何直接用自定义数组创建Eigen稀疏矩阵,避免内存冗余?
直接用自定义数组构造Eigen稀疏矩阵(避免Triplet冗余内存)
Eigen默认的Triplet容器会额外分配内存存储三元组结构体,确实会造成冗余。你可以直接利用现有三个自定义数组(行索引、列索引、值)来构造稀疏矩阵,无需reserve或push_back,具体方法分两种场景:
1. 数组为未排序COO格式(通用场景)
如果你的三个数组是未排序的COO格式(行/列索引无特定顺序),可以直接遍历现有数组插入元素,不需要额外的Triplet容器:
// 假设: // rows: 自定义行索引数组(int类型,长度nnz) // cols: 自定义列索引数组(int类型,长度nnz) // vals: 自定义值数组(double类型,长度nnz) // n: 矩阵的行数/列数(假设是方阵) Eigen::SparseMatrix<double> mat(n, n); // 预分配非零元素空间(仅分配内部CSC/CSR所需内存,无冗余) mat.reserve(nnz); // 直接遍历自定义数组插入元素 for (int i = 0; i < nnz; ++i) { mat.insert(rows[i], cols[i]) = vals[i]; } // 压缩矩阵(可选,优化后续运算性能) mat.makeCompressed();
这种方式直接复用你已有的三个数组内存,仅为Eigen的稀疏矩阵内部结构分配必要内存,避免了Triplet容器的冗余开销。
2. 数组为已排序格式(更高效)
如果你的数组已经按**列优先(CSC)或行优先(CSR)**排序,可以直接填充Eigen稀疏矩阵的底层存储,跳过插入排序步骤,进一步提升效率:
列优先(CSC)示例
Eigen::SparseMatrix<double, Eigen::ColMajor> mat(n, n); mat.resizeNonZeros(nnz); // 第一步:构建列指针数组(outerIndex) Eigen::VectorXi outer_index(n + 1); outer_index.setZero(); for (int i = 0; i < nnz; ++i) { // Eigen默认是0-based索引,若你的数组是1-based需减1 outer_index(cols[i] + 1)++; } // 计算前缀和得到列指针 std::partial_sum(outer_index.data(), outer_index.data() + n + 1, outer_index.data()); // 第二步:直接拷贝现有数组到矩阵底层 std::copy(rows, rows + nnz, mat.innerIndexPtr()); std::copy(vals, vals + nnz, mat.valuePtr()); std::copy(outer_index.data(), outer_index.data() + n + 1, mat.outerIndexPtr());
行优先(CSR)示例
只需将矩阵类型改为RowMajor,并构建行指针数组:
Eigen::SparseMatrix<double, Eigen::RowMajor> mat(n, n); mat.resizeNonZeros(nnz); // 构建行指针数组(outerIndex) Eigen::VectorXi outer_index(n + 1); outer_index.setZero(); for (int i = 0; i < nnz; ++i) { outer_index(rows[i] + 1)++; } std::partial_sum(outer_index.data(), outer_index.data() + n + 1, outer_index.data()); // 拷贝数据到矩阵底层 std::copy(cols, cols + nnz, mat.innerIndexPtr()); std::copy(vals, vals + nnz, mat.valuePtr()); std::copy(outer_index.data(), outer_index.data() + n + 1, mat.outerIndexPtr());
注意事项
- 索引基:Eigen默认使用0-based索引,如果你的自定义数组是1-based(和Fortran MKL一致),需要在插入或拷贝前将
rows[i]和cols[i]减1。 - 内存安全性:确保自定义数组的生命周期覆盖稀疏矩阵的使用周期,避免悬空指针。
内容的提问来源于stack exchange,提问作者Mitto
相关产品推荐
相关产品推荐

