2013-07-26 164 views
2

我有这样的代码,其调用C++方法在Java在for循环中:灌装在本征稀疏矩阵是非常慢

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是这些值的索引。

我在本文中读取插入函数最快的特征文件,当非零系数的数目大约为5000时就可以。但是,当我有25000时,每列需要5秒!

我试过insrtback,但值是一样的吗?这个命令究竟做了什么?有什么方法可以改善此代码吗?

一旦优势(也许):每列中的值和索引是通过从最高到最低值进行排序...

+0

你是否用增加pozic值或随机模式来调用此函数?同样,如果该值按“从最高到最低”排序,则反转循环,使插入命令归结为简单推回。保留命令不正确。 – ggael

+0

1.是的,增加; pozic从0到sizeA的matA列。下一个你的意思是储备com。采取从这种方法初始化方法matA.??????????????或什么coorect方式ow写保留命令? –

+0

那么最快的是打电话预约(大小); matA.startVec(pozic); for ...(...)mat.insertBack(fltind2 [jm],pozic)= ...;确保fltind2 [jm]的顺序不断增加。 – ggael

回答

2

如果你的稀疏矩阵很大,你必须在填写前分配足够的空间马塔它。否则,需要很长的时间来重复分配空间和复制数据。

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

按照上述过程,我能够填补47236x677399稀疏矩阵(#非零:49556258)在30秒内使用普通的笔记本电脑。如果我不这样做,它永远......

1

Eigen Sparse Matrix Tutorial要点:

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 

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

线4执行用于柱主要情况下的排序的插入。对于速度来说,填充第j列时,现有的非零应该具有小于i的行索引。然后,这个操作归结为微不足道的O(1)操作。

第5行抑制剩余空的空间和基体转变成压缩的列的存储。