C++ LAPACK函数在第一次迭代后变慢

C++ LAPACK函数在第一次迭代后变慢,c++,performance,iteration,lapack,C++,Performance,Iteration,Lapack,我正在实现一个迭代算法,该算法使用LAPACK进行PSD投影(其实并不重要,关键是我反复调用此函数): void useLAPACK(向量&x,整数N){ /*当地人*/ int n=n,il,iu,m,lda=n,ldz=n,info,lwork,liwork; 双重禁欲; 双vl,vu; 国际iwkopt; 国际工作; 双wkopt; 双重*工作; /*本地阵列*/ int isuppz[N]; 双w[N],z[N*N]; /*负Absol表示使用默认值*/ Absol=-1.0; /*设置

我正在实现一个迭代算法,该算法使用LAPACK进行PSD投影(其实并不重要,关键是我反复调用此函数):

void useLAPACK(向量&x,整数N){
/*当地人*/
int n=n,il,iu,m,lda=n,ldz=n,info,lwork,liwork;
双重禁欲;
双vl,vu;
国际iwkopt;
国际工作;
双wkopt;
双重*工作;
/*本地阵列*/
int isuppz[N];
双w[N],z[N*N];
/*负Absol表示使用默认值*/
Absol=-1.0;
/*设置il,iu以计算选定的最小特征值*/
vl=0;
vu=1.79769e+308;
/*查询并分配最佳工作空间*/
lwork=-1;
liwork=-1;
dsyevr_((字符*)“向量”、(字符*)“V”、(字符*)“上”、&n、&x[0]、&lda、&vl、&vu、&il、&iu、,
&Absol,&m,w,z,&ldz,isuppz,&wkopt,&lwork,&iwkopt,&liwork,
&信息);
lwork=(int)wkopt;
工作=(双*)malloc(工作*大小(双));
liwork=iwkopt;
iwork=(int*)malloc(liwork*sizeof(int));
/*求解特征值问题*/
dsyevr_((字符*)“向量”、(字符*)“V”、(字符*)“上”、&n、&x[0]、&lda、&vl、&vu、&il、&iu、,
&Absol,&m,w,z,&ldz,isuppz,work,&lwork,iwork,&liwork,
&信息);
/*检查收敛性*/
如果(信息>0){
printf(“dsyevr(useLAPACK)无法计算特征值。\n”);
出口(1);
}
/*打印找到的特征值的数目*/
//printf(“\n找到的特征值总数:%2i\n”,m);
//打印矩阵(“选定特征值”,1,m,w,1);
//打印矩阵(“选定特征向量(按列存储)”,n,m,z,ldz;
//特征向量作为堆叠列返回(总计m)
//外和运算速度最快。
对于(inti=0;i

现在,我的时间测量显示,第一次通话大约需要4毫秒,但随后会增加到100毫秒。这段代码对此有很好的解释吗?每次x都是相同的向量。

我想我已经解决了这个问题。我的算法从零矩阵开始,然后正特征值的数量或多或少是半正半负。dsyevr仅计算具有这些参数的正特征值和相应的特征向量。我想如果所有的都是零,它实际上不需要计算任何特征向量,这使得算法更快。谢谢你的回答,对丢失的信息感到抱歉。

我想我已经解决了这个问题。我的算法从零矩阵开始,然后正特征值的数量或多或少是半正半负。dsyevr仅计算具有这些参数的正特征值和相应的特征向量。我想如果所有的都是零,它实际上不需要计算任何特征向量,这使得算法更快。感谢您提供的所有答案,并对丢失的信息表示歉意。

像往常一样,对于此类问题,您是如何衡量这些时间安排的?
N
有多大?这只是个想法。在第一次迭代后,是否检查数组是否未被NaN值污染?->NaN值通常会降低计算速度,因为它们会生成调用微码的异常(在英特尔cpu上)@PicaudVincent Well他说,
x
每次都是同一个向量,其他一切都是局部的,所以我们可以假设情况并非如此。不断的重新分配可能没有帮助。@Qubit,谢谢你的反馈。这只是一个想法,我没有其他想法。。。祝你的问题好运。和往常一样,这种类型的问题,你是如何衡量这些时间安排的?
N
有多大?这只是个想法。在第一次迭代后,是否检查数组是否未被NaN值污染?->NaN值通常会降低计算速度,因为它们会生成调用微码的异常(在英特尔cpu上)@PicaudVincent Well他说,
x
每次都是同一个向量,其他一切都是局部的,所以我们可以假设情况并非如此。不断的重新分配可能没有帮助。@Qubit,谢谢你的反馈。这只是一个想法,我没有其他想法。。。祝你的问题好运。
void useLAPACK(vector<double>& x, int N){

    /* Locals */
    int n = N, il, iu, m, lda = N, ldz = N, info, lwork, liwork;
    double abstol;
    double vl,vu;
    int iwkopt;
    int* iwork;
    double wkopt;
    double* work;
    /* Local arrays */
    int isuppz[N];
    double w[N], z[N*N];

    /* Negative abstol means using the default value */
    abstol = -1.0;
    /* Set il, iu to compute NSELECT smallest eigenvalues */
    vl = 0;
    vu = 1.79769e+308;
    /* Query and allocate the optimal workspace */
    lwork = -1;
    liwork = -1;
    dsyevr_( (char*)"Vectors", (char*)"V", (char*)"Upper", &n, &x[0], &lda, &vl, &vu, &il, &iu,
             &abstol, &m, w, z, &ldz, isuppz, &wkopt, &lwork, &iwkopt, &liwork,
             &info );
    lwork = (int)wkopt;
    work = (double*)malloc( lwork*sizeof(double) );
    liwork = iwkopt;
    iwork = (int*)malloc( liwork*sizeof(int) );
    /* Solve eigenproblem */
    dsyevr_( (char*)"Vectors", (char*)"V", (char*)"Upper", &n, &x[0], &lda, &vl, &vu, &il, &iu,
             &abstol, &m, w, z, &ldz, isuppz, work, &lwork, iwork, &liwork,
             &info );
    /* Check for convergence */
    if( info > 0 ) {
        printf( "The dsyevr (useLAPACK) failed to compute eigenvalues.\n" );
        exit( 1 );
    }
    /* Print the number of eigenvalues found */
    //printf( "\n The total number of eigenvalues found:%2i\n", m );
    //print_matrix( "Selected eigenvalues", 1, m, w, 1 );
    //print_matrix( "Selected eigenvectors (stored columnwise)", n, m, z, ldz );
    //Eigenvectors are returned as stacked columns (in total m)
    //Outer sum calculation is fastest.
    for(int i = 0; i < N*N; ++i) x[i] = 0;
    double lambda;
    double vrow1,vrow2;
    for(int col = 0; col < m; ++col) {
        lambda = w[col];
        for (int row1 = 0; row1 < N; ++row1) {
            vrow1 = z[N*col+row1];
            for(int row2 = 0; row2 < N; ++row2){
                vrow2 = z[N*col+row2];
                x[row1*N+row2]  += lambda*vrow1*vrow2;
            }
        }
    }
    free( (void*)iwork );
    free( (void*)work );
}