代码之家  ›  专栏  ›  技术社区  ›  Daiver

在没有内存开销的情况下设置特征::稀疏矩阵的稀疏模式

  •  1
  • Daiver  · 技术社区  · 7 年前

    我已经知道了 (我有唯一的排序列索引和行偏移量)。显然,通过setFromTriplets是可能的,但不幸的是,setFromTriplets需要很多额外的内存(至少在我的例子中是这样)

    const long nRows = 5000000;
    const long nCols = 100000;
    const long nCols2Skip = 1000;
    //It's quite big!
    const long nTriplets2Reserve = nRows * (nCols / nCols2Skip) * 1.1;
    Eigen::SparseMatrix<double, Eigen::RowMajor, long> mat(nRows, nCols);
    
    std::vector<Eigen::Triplet<double, long>> triplets;
    
    triplets.reserve(nTriplets2Reserve);
    for(long row = 0; row < nRows; ++row){
        for(long col = 0; col < nCols; col += nCols2Skip){
            triplets.push_back(Eigen::Triplet<double, long>(row, col, 1));
        }
    }
    std::cout << "filling mat" << std::endl << std::flush;
    mat.setFromTriplets(triplets.begin(), triplets.end());
    
    std::cout << "Finished! nnz " << mat.nonZeros() << std::endl;
    //Stupid way to check memory consumption
    std::cin.get();
    

    htop

    所以我有两个问题:

    1. 如何以尽可能少的开销填充特征::稀疏矩阵的稀疏模式

    如果我的例子错了,请告诉我。

    我的Eigen版本是3.3.2

    编辑: 看起来像是 inserting (带 preallocation

    1 回复  |  直到 7 年前
        1
  •  3
  •   chtz    7 年前

    广告1:你甚至可以比普通人更有效率 insert 通过使用内部函数 startVec insertBack ,如果可以保证按词典顺序插入元素。

    setFromTriplets 您需要大约两倍于矩阵最终大小(加上三元组容器的大小),因为元素首先插入到矩阵的转置版本中,然后转置到最终矩阵,以确保所有内部向量都已排序。如果您提前知道矩阵的结构,这显然是相当浪费内存,但它旨在处理任意输入数据。

    Triplet 需要8+8+8=24字节(对于 vector )稀疏矩阵的每个元素需要8+8=16字节(一个 double 对于值,一 long

    奖金: Eigen::SparseBase<> (但我不建议这样做,除非内存/性能对您来说非常关键,并且您愿意阅读大量“稀疏”的内部特征码…)。然而,在这种情况下,可能更容易考虑您打算对矩阵执行什么操作,并尝试仅为此执行特殊操作。