Cuda cusparse csrsv_分析的性能非常慢

Cuda cusparse csrsv_分析的性能非常慢,cuda,linear-algebra,sparse-matrix,Cuda,Linear Algebra,Sparse Matrix,我用LU预处理编写了一个共轭梯度解算器(用于线性方程组),我使用了Maxim Naumov博士在nvidia研究社区的研究作为指导,残差更新步骤需要求解下三角矩阵系统,然后求解上三角矩阵系统分为两个阶段: 分析阶段(利用稀疏模式并决定并行化级别) 解决方案阶段本身 根据与本主题相关的所有帖子,以及Naumov的论文本身,分析阶段明显比求解阶段慢,但它只执行了一次,因此在考虑整个执行时间时,这不应该是一个问题。然而,在我的程序中,分析阶段需要大约35-45%的整个求解时间(执行所有迭代所需的时间!

我用LU预处理编写了一个共轭梯度解算器(用于线性方程组),我使用了Maxim Naumov博士在nvidia研究社区的研究作为指导,残差更新步骤需要求解下三角矩阵系统,然后求解上三角矩阵系统分为两个阶段:

  • 分析阶段(利用稀疏模式并决定并行化级别)
  • 解决方案阶段本身
  • 根据与本主题相关的所有帖子,以及Naumov的论文本身,分析阶段明显比求解阶段慢,但它只执行了一次,因此在考虑整个执行时间时,这不应该是一个问题。然而,在我的程序中,分析阶段需要大约35-45%的整个求解时间(执行所有迭代所需的时间!),这很烦人,另一件事是我很确定矩阵的稀疏模式不允许大量并行化,因为几乎所有元素都需要已知以前的元素(因为在CFD中,每个节点至少需要相邻的6个节点(六面体体积)在它周围,每一行都会重复),所以分析阶段无论如何都不会很有用

    matrixLU在该代码中同时包含上下三角矩阵,上三角矩阵使用原始矩阵对角线,下三角矩阵具有单位对角线(LU分解)

    那么,有人知道为什么分析阶段如此之慢吗?它是如何加速的?是(分析阶段执行时间)/(求解阶段执行时间)比率取决于GPU吗

    编辑: 我在很多情况下都尝试过此解算器,结果非常接近,但在我关心的特定情况下,它具有以下条件:

    • 大小(N):~860000*860000
    • 非零数量(NZ):~6000000
    • 收敛所需的迭代次数:10
    • 分析阶段执行时间:210毫秒
    • 求解阶段执行时间(总结所有迭代):350毫秒
    • 所有浮点运算均以双精度格式执行
    • GPU:GeForce GTX 550 Ti
    • 操作系统:Windows7ultimate,64位

    我联系了NVIDIA的线性代数库团队,他们提供了以下反馈

  • 关于绩效结果:

  • CG迭代法仅执行10次迭代,直到找到线性系统的解。在这种情况下,这似乎不足以使分析阶段所消耗的时间氨化。(编辑:)收敛到解决方案所需的步骤数在不同的应用程序中有所不同。在一些非条件迭代方法中,不收敛(或需要数千次迭代),而预条件迭代方法需要几十次(或数百次)在这个特定的应用中,迭代方法在10次迭代中收敛,这一事实并不一定代表所有的应用

  • 分析和求解阶段的比率为6=210/35,这与我们在其他矩阵上的实验一致,通常在区间[4,10]内。目前尚不清楚分析和求解阶段的时间与CPU上稀疏三角形求解所花费的时间相比如何。(这将是一个有趣的信息。)

  • 关于算法:
  • 不幸的是,您只能做一些事情来恢复一点点性能(没有真正的方法来加速分析阶段)。例如,您可以将矩阵Xlu拆分为单独的下三角部分和上三角部分。使用单独的三角部分进行计算通常比使用嵌入到一般矩阵中的三角部分进行计算更快。如果使用填充为0的不完全因子分解作为预条件,您还可以利用不完全LU/ChoLexy在GPU上填充了0,这在CuSpCeSE库中已经成为可用的了。(强> >编辑:< /强>)在CUDA工具包5版本中,0填充的不完全LU分解可用。当前版本的这个版本的发布可以在英伟达网站上获得。
  • 我们从未研究过不同GPU之间分析和求解阶段的比率如何变化;我们所有的实验都是在C2050上进行的
  • 分析阶段比较慢,因为它必须收集关于哪些行可以一起处理为级别的信息。求解阶段比较快,因为它只处理级别(请参阅)
  • 最后,您还提到,您认为问题中没有足够的并行性。但是,仅从矩阵来看,并行性的大小可能很难猜测。如果确实没有多少并行性(每一行取决于前一行),则CUSPARSE稀疏三角形解可能不是解决此问题的正确算法。此外,您可以尝试运行CG迭代方法,而无需预处理或使用其他类型的预处理程序,这些预处理程序可能更适合您的问题

    如前所述,了解这段代码在GPU和CPU上的性能比较是很有趣的

    编辑: 关于一些评论……如前所述,预处理迭代方法的最终迭代次数在不同的应用程序中有所不同。在某些情况下,它可能非常小(例如,在您的应用程序中为10次),但在其他情况下,它可能相对较大(以100秒为单位)。本文的重点不是“胜利”,但r
    // z = inv(matrixLU)*r
    cusparseMatDescr_t descrL = 0 ;
    cusparseMatDescr_t descrU = 0 ;
    cusparseStatus = cusparseCreateMatDescr(&descrL) ;
    cusparseStatus = cusparseCreateMatDescr(&descrU) ;
    
    cusparseSetMatType(descrL,CUSPARSE_MATRIX_TYPE_GENERAL) ;
    cusparseSetMatIndexBase(descrL,CUSPARSE_INDEX_BASE_ONE) ;
    cusparseSetMatDiagType(descrL,CUSPARSE_DIAG_TYPE_UNIT) ;
    cusparseSetMatFillMode(descrL,CUSPARSE_FILL_MODE_LOWER) ;
    
    cusparseSetMatType(descrU,CUSPARSE_MATRIX_TYPE_GENERAL) ;
    cusparseSetMatIndexBase(descrU,CUSPARSE_INDEX_BASE_ONE) ;
    cusparseSetMatDiagType(descrU,CUSPARSE_DIAG_TYPE_NON_UNIT) ;
    cusparseSetMatFillMode(descrU,CUSPARSE_FILL_MODE_UPPER) ;
    
    cusparseSolveAnalysisInfo_t inforL = 0 ;
    cusparseSolveAnalysisInfo_t inforU = 0 ;
    cusparseStatus = cusparseCreateSolveAnalysisInfo(&inforL) ;
    cusparseStatus = cusparseCreateSolveAnalysisInfo(&inforU) ;
    
    double startFA = omp_get_wtime() ;
    cusparseStatus = cusparseDcsrsv_analysis(cusparseHandle, CUSPARSE_OPERATION_NON_TRANSPOSE, N, NZ, descrL, matrixLU, iRow, jCol, inforL) ;
    if(cusparseStatus != CUSPARSE_STATUS_SUCCESS) printf("%s \n\n","cusparseDcsrsv_analysis1 Error !") ;
    cusparseStatus = cusparseDcsrsv_analysis(cusparseHandle, CUSPARSE_OPERATION_NON_TRANSPOSE, N, NZ, descrU, matrixLU, iRow, jCol, inforU) ;
    if(cusparseStatus != CUSPARSE_STATUS_SUCCESS) printf("%s \n\n","cusparseDcsrsv_analysis2 Error !") ;
    double finishFA = omp_get_wtime() ;