在 Eigen 中填充稀疏矩阵非常慢

Dan*_*ova 5 c++ matrix eigen

我有这段代码,它在 for 循环中调用 java 中的 c++ 方法:

JNIEXPORT void JNICALL Java_com_jp_algi_CoreC_MMload(JNIEnv *env3, jobject clazz3, jdoubleArray inputv, jintArray inputi, jint poc, jint pozic)
{
    jdouble* fltv2 ;
    jint* fltind2;
    jsize sizedat = env3->GetArrayLength(inputi);
    fltv2  = new jdouble[sizedat];
    fltind2  = new jint[sizedat];
    jint i;
    jint jm;
    env3->GetIntArrayRegion(inputi,0,sizedat,fltind2);
    env3->GetDoubleArrayRegion(inputv,0,sizedat,fltv2);

    // default is column major
    matA.reserve(VectorXi::Constant(1,sizedat));

    for ( jm = 0; jm < sizedat; jm++) {
        //matA.insert(fltind2[jm],pozic) = fltv2[jm]; // alternative: mat.coeffRef(i,j) += v_ij;
        matA.insert(fltind2[jm],pozic)= fltv2[jm];
        //matA.insertBack(fltind2[jm],pozic)= fltv2[jm];
        //matA.ins
        //matA.insertBackUncompressed();
        //matA.coeffRef(fltind2[jm],pozic) += fltv2[jm];
        // optional
    }

    matA.makeCompressed();

    //k++; //blbe zayklenji!!!
    env3->SetIntArrayRegion(inputi,0,sizedat,fltind2);
    env3->SetDoubleArrayRegion(inputv,0,sizedat,fltv2);
    delete[] fltv2;
    delete[] fltind2;
}
Run Code Online (Sandbox Code Playgroud)

其中 inputv 是 matA 的列的值。和 inputi 是这些值的索引。

我在 eigen 的文档中读到插入函数是最快的,当非零系数的数量约为 5000 时就可以了。但是当我有 25000 时,每列需要 5 秒!

我试过insrtback,但值是一样的?这个命令到底是做什么的?有什么方法可以改进这段代码吗?

曾经的优势(也许):每列中的值和索引按值从高到低排序......

小智 4

如果您的稀疏矩阵很大,则必须在填充之前为 matA 分配足够的空间。否则,会需要很长很长的时间来一遍又一遍地分配空间和复制数据。

您需要做的第一件事是了解矩阵的稀疏模式。我所说的稀疏模式是指每列的非零元素的数量(假设您的稀疏矩阵位于主列)。如果我们将这些值存储在 类型的变量 V 中VectorXi,调用matA.reserve(V)就是分配足够的内存空间。

按照上述过程,我可以使用普通笔记本电脑在 30 秒内填充 47236x677399 稀疏矩阵 (#non-zeros:49556258)。如果我不这样做的话,这将需要永远......