用PETSc实现预条件共轭梯度

时间:2017-01-13 21:20:56

标签: c matlab gradient-descent petsc

我正在编写一些C代码,在大约4千万次观测的大型数据集上运行OLS。我感兴趣的是使用预处理共轭梯度算法(PCG)利用不完全Cholesky(ICC)分解来获得预处理器。我有一个正确执行相同的MATLAB代码,并将其用作基准以确保C脚本正确。简而言之,我想复制MATLAB" ichol"和" pcg"程序使用C.

目前,我正在使用PETSc C库进行PCG和ICC。我使用R来读入数据集并计算X&X; X和X' Y和I输出两个文本文件供C使用。矩阵采用坐标稀疏格式(3个向量 - 一个带行索引,一个具有列索引,一个具有所有非零矩阵条目的值)。完整矩阵的大小约为800万到800万,约有1.66亿非零条目。

我读入C中的文件,构造矩阵和向量,并使用PETSc的程序KSPSolve运行PCG,将线性系数b的向量输出到文本文件。代码完成顺利完成,但我得到的解决方案是荒谬的 - 系数大约为200万,当我应该得到类似2或3的东西(来自运行MATLAB代码)。

但是,当我将数据集限制为较小的子样本(例如,前300,000个观察值)时,C代码和MATLAB代码的结果非常吻合。经过一些试验和错误后,我确定结果一致,直到我达到一个非常特定的样本大小(363,855),此时C代码结果开始发散。分歧并没有突然爆发 - 首先,C代码和MATLAB代码之间的最大绝对差值大约为700,但它很快就会增长到上面提到的200万。我查看了PETSc的内部收敛监测统计数据,程序本身似乎认为真实残差的范数(X' Y-X' Xb)下降到相当低的水平(10 ^的数量级) (-3)),如果我使用C的输出在MATLAB中手动计算残差,我会得到非常大的数字。更重要的是,如果我从最后一个(而不是第一个)363,855甚至100万个观测值中获取子样本,那么C代码和MATLAB代码仍然可以很好地对齐。

我正在寻找有关此处可能出现的问题以及采取哪些措施来诊断/解决问题的建议。我对C来说相当新,所以基本的错误肯定是可能的。

代码的相关部分粘贴在下面:

/* Read in matrix, rhs, and IA, JA, RA vectors from ascii files */

   ierr   = PetscPrintf(PETSC_COMM_SELF,"\n Read matrix in ascii format ...\n");CHKERRQ(ierr);
   ierr   = PetscFOpen(PETSC_COMM_SELF,Ain,"r",&Afile);CHKERRQ(ierr);
   nsizes = 3;
   fscanf(Afile,"%d,%d,%d\n",&m,&n,&nz);
   ierr = PetscPrintf(PETSC_COMM_SELF,"m: %d, n: %d, nz: %d \n", m,n,nz);CHKERRQ(ierr);

/*Allocating matrix and vectors*/

   ierr = MatCreate(PETSC_COMM_SELF,&A);CHKERRQ(ierr);
   ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr);
   ierr = MatSetFromOptions(A);CHKERRQ(ierr);
   ierr = MatSeqAIJSetPreallocation(A,nz/m,nnz_array);CHKERRQ(ierr);
   ierr = MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);


/*Building matrix*/

    for (i=0; i<nz; i++) {
      fscanf(Afile,"%g,%g,%le\n",&_row,&_col,(double*)&val);
      row = (PetscInt)_row;
      col = (PetscInt)_col;
      ierr = MatSetValues(A,1,&row,1,&col,&val,INSERT_VALUES);
      CHKERRQ(ierr);

    }

    ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
    ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
    fflush(stdout);
    fclose(Afile);
    free(nnz_array);

  /*Reading-in X'Y vector*/
  ierr = VecCreate(PETSC_COMM_SELF,&b);CHKERRQ(ierr);
  ierr = VecSetSizes(b,PETSC_DECIDE,n);CHKERRQ(ierr);
  ierr = VecSetFromOptions(b);CHKERRQ(ierr);
  ierr = PetscPrintf(PETSC_COMM_SELF,"\n Read rhs in ascii format ...\n");CHKERRQ(ierr);
  ierr = PetscFOpen(PETSC_COMM_SELF,rhs,"r",&bfile);CHKERRQ(ierr);
    for (i=0; i<n; i++) {
      fscanf(bfile,"%d,%le\n",&dummy,(double*)&val);
      ierr = VecSetValues(b,1,&i,&val,INSERT_VALUES);CHKERRQ(ierr);
    }
    ierr = VecAssemblyBegin(b);CHKERRQ(ierr);
    ierr = VecAssemblyEnd(b);CHKERRQ(ierr);
    fflush(stdout);
    fclose(bfile);

  /*Creating vector to store solution in*/
  ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) x, "Solution");CHKERRQ(ierr);
  ierr = VecSetSizes(x,PETSC_DECIDE,n);CHKERRQ(ierr);
  ierr = VecSetFromOptions(x);CHKERRQ(ierr);

  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                Create the linear solver and set various options
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  /*
     Create linear solver context
  */
  ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr);

  /*
     Set operators. Here the matrix that defines the linear system
     also serves as the preconditioning matrix.
  */
  ierr = KSPSetOperators(ksp,A,A);CHKERRQ(ierr);

  /*
     Set linear solver defaults for this problem.
  */
  ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
  ierr = PCSetType(pc,PCICC);CHKERRQ(ierr);
  ierr = KSPSetTolerances(ksp,1.e-10,1.e-10,PETSC_DEFAULT,1000);CHKERRQ(ierr);
  ierr = KSPSetType(ksp,KSPCG);
  /*
    Set runtime options.
  */
  ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);

  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                      Solve the linear system
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  /*
     Solve linear system
  */
    printf("\nBeginning to solve system:\n"); 
    ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr);


  /*
     View solver info.
  */
  ierr = KSPView(ksp,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);

0 个答案:

没有答案