我用LU预处理编写了一个共轭梯度求解器(用于线性方程组),我在nvidia的研究界使用了Maxim Naumov博士的papers作为指导,残差更新步骤,需要求解更低三角矩阵系统然后求解上三角矩阵系统分为两个阶段:
根据与该主题相关的所有帖子,以及Naumov的论文本身,分析阶段明显慢于解决阶段,但它执行了一次,因此考虑整个执行时间时不应该是一个问题然而,在我的程序中,分析阶段需要整个解决时间的约35-45%(执行所有迭代所需的时间!),这非常烦人,另一件事是我很确定矩阵的稀疏模式不允许进行大量的并行化,因为几乎所有元素都需要知道先前的元素(因为在CFD中,每个节点至少需要相邻的6个节点(六面体体积),并且每个节点都重复),所以分析阶段无论如何都不会很有用!
此代码中的matrixLU 包含上三角矩阵和下三角矩阵,上三角矩阵使用原始矩阵对角线,下三角矩阵具有统一对角线(LU因式分解)。
// 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() ;
那么,任何人都知道分析阶段为何如此缓慢?以及它如何加速?是(分析阶段执行时间)/(解决阶段执行时间)比率 GPU依赖?
修改 我在很多情况下试过这个求解器,结果很接近,但在我关注的具体情况下,它有以下条件:
答案 0 :(得分:5)
我联系了NVIDIA的线性代数图书馆团队,他们提供了以下反馈。
关于绩效结果:
CG迭代方法仅执行10次迭代,直到找到线性系统的解。在这种情况下,似乎没有足够的迭代来分摊分析阶段所消耗的时间。 (编辑:) 收敛到解决方案所需的步骤数因应用程序而异。在一些未经处理的迭代方法中,不会聚(或进行数千次迭代),并且预处理的迭代方法需要数十(或数百)次迭代才能收敛到解。在这个特定应用中,迭代方法在10次迭代中收敛的事实并不一定代表所有应用。
分析和解决阶段的比例为6 = 210/35,这与我们在其他矩阵上的实验一致,其中它通常在区间[4,10]。目前尚不清楚分析和求解阶段的时间与CPU上稀疏三角形求解所花费的时间之间的比较。 (这将是有趣的信息。)
最后,您还提到您认为问题中没有足够的并行性。但是,通过查看矩阵,很难猜测并行度。如果确实存在很少的并行性(每行依赖于前一行),则CUSPARSE稀疏三角形求解可能不是该问题的正确算法。此外,您可以尝试在没有预处理的情况下运行CG迭代方法,或者使用可能更适合您的问题的其他类型的预处理器。
如前所述,了解此代码的性能如何在GPU和CPU上进行比较会很有趣。
修改强> 关于一些评论......如前所述,预处理迭代方法的最终迭代次数在不同的应用程序中有所不同。在某些情况下,它可能非常小(例如,在您的应用程序中为10),但在其他情况下,它可能相对较大(以100秒为单位)。本文不是关注“胜利”,而是关注算法的权衡。它试图让用户更深入地了解例程,以便有效地使用它。同样,如果手头的稀疏模式没有任何并行性,这对你来说不是正确的算法。
关于CPU和GPU比较,存在一些问题(例如密集矩阵矩阵或稀疏矩阵向量乘法),其中GPU很棒,还有其他问题(例如遍历链表或完全执行它没有的顺序代码片段。稀疏三角形线性系统的解决方案位于这些算法之间(取决于系数矩阵的稀疏模式和线性系统的其他属性,它可能或不适合您)。此外,使用GPU的决定不仅仅基于单个算法,例如稀疏三角形求解,而是基于应用程序使用的整个算法集。最终,GPU通常非常成功地加速和改进整个应用程序的性能。
最后,关于trsm与csrsv,我们并不感到惊讶的是,对于在密集存储中执行操作的小矩阵比在稀疏存储中执行操作更快(即使这些小矩阵可能是稀疏的)。这通常不仅对于三角形求解而且对于其他线性代数运算也是如此(尽管可能在不同的交叉点处发生,这取决于矩阵的操作和稀疏模式)。此外,稀疏三角形求解算法再次设计为在迭代设置中运行,其中分析一次完成并且多次完成求解。因此,运行一次(并在分析阶段计算)并不奇怪,这种操作的更高交叉点在稀疏而不是密集格式中更有效。