5

我有这段代码在 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;
}

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

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

我试过insrtback,但值是一样的吗?这个命令具体是做什么的?有没有办法改进这段代码?

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

4

2 回答 2

4

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

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

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

于 2013-08-10T00:40:59.597 回答
2

本征稀疏矩阵教程的要点:

1: SparseMatrix<double> mat(rows,cols);         // default is column major
2: mat.reserve(VectorXi::Constant(cols,x));
3: for each i,j such that v_ij != 0
4:   mat.insert(i,j) = v_ij;                    // alternative:  mat.coeffRef(i,j) += v_ij;
5: mat.makeCompressed();                        // optional

这里的关键因素是第 2 行,我们为每列保留 x 个非零的空间。在许多情况下,可以很容易地预先知道每列或每行的非零数。如果每个内部向量的变化很大,那么可以通过为向量对象提供一个返回第 j 个内部向量的保留大小的 operator[](int j) 来指定每个内部向量的保留大小(例如,通过 VectorXi 或 std::vector)。如果只能粗略估计每个内部向量的非零数,强烈建议高估它而不是相反。如果省略此行,则第一次插入新元素将为每个内部向量保留 2 个元素的空间。

第 4 行对 Column 主要情况执行排序插入。为了提高速度,在填充第 j 列时,现有的非零值应该具有小于 i 的行索引。然后,此操作归结为琐碎的 O(1) 操作。

第 5 行抑制剩余的空白空间并将矩阵转换为压缩列存储。

于 2015-04-30T12:08:15.973 回答