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分解

// 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

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

尺寸N:~860000*860000 非零数量新西兰:~6000000 收敛所需的迭代次数:10 分析阶段执行时间:210毫秒 求解阶段执行时间,将所有迭代相加:350 ms 所有浮点运算均以双精度格式执行 GPU:GeForce GTX 550 Ti 操作系统:Windows 7 ultimate,64位
我联系了NVIDIA的线性代数库团队,他们提供了以下反馈

关于绩效结果:

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

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

关于算法: 不幸的是,您只能做几件事来恢复一点性能—没有真正的方法来加速分析阶段。例如,可以将matrixLU拆分为单独的上下三角形部分。使用单独的三角形部件进行计算通常比使用嵌入在一般矩阵中的三角形部件进行计算要快。如果使用0填充的不完全因子分解作为预条件,还可以利用GPU上0填充的不完全LU/Cholesky,这最近在CUSPARSE库中可用。编辑:CUDA Toolkit 5.0版本中提供了0填充的不完整LU分解。目前,这个版本的早期访问版本可以通过英伟达网站获得。 我们从未研究过不同GPU之间分析和求解阶段的比率如何变化;我们所有的实验都是在C2050上进行的。 分析阶段很慢,因为它必须收集关于哪些行可以一起处理为级别的信息。“求解”阶段更快,因为它只处理所看到的级别。 最后,您还提到您认为问题中没有足够的并行性。但是,仅仅从矩阵的角度,就很难猜测并行性的大小。如果每一行依赖于前一行的并行性确实很小,那么CUSPARSE稀疏三角求解可能不是解决此问题的正确算法。此外,您可以尝试在不进行预处理的情况下运行CG迭代方法,或者使用可能更适合您的问题的其他类型的预处理器

如前所述,我 我想知道这段代码在GPU和CPU上的性能比较如何

编辑: 关于一些评论。。。如前所述,预处理迭代方法的最终迭代次数在不同的应用程序中有所不同。在某些情况下,它可能非常小,例如,在应用程序中为10,但在其他情况下,它可能在100秒内相对较大。本文的重点不是“胜利”,而是算法的权衡。它试图让用户更深入地理解例程,以便有效地使用它。同样,如果手头的稀疏模式没有任何并行性,那么这不是适合您的算法

关于CPU和GPU的比较,有一些问题,例如GPU擅长的密集矩阵或稀疏矩阵向量乘法,还有一些问题,例如遍历链表或执行完全连续的代码段,而GPU不擅长这些问题。稀疏三角形线性系统的解介于这些算法之间,取决于系数矩阵的稀疏模式和线性系统的其他属性,它可能对您有效,也可能对您无效。此外,使用GPU的决定不仅基于单个算法,例如稀疏三角求解,而是基于应用程序使用的整个算法集。最终,GPU通常能够非常成功地加速和提高整个应用程序的性能


最后,关于trsm与csrsv,对于在密集存储中执行操作的小矩阵,即使这些小矩阵可能是稀疏的,也要比在稀疏存储中执行操作快,这并不奇怪。这通常不仅适用于三角求解,也适用于其他线性代数运算,但它可能发生在不同的交叉点上,具体取决于运算和矩阵的稀疏模式。同样,稀疏三角形求解算法被设计为在迭代环境中运行,在迭代环境中分析一次,求解多次。因此,在分析阶段运行一次并计数,会导致更高的交叉点,从而使此操作在稀疏格式中比在密集格式中更有效,这并不奇怪

运行此代码的问题大小、GPU和操作系统是什么?@talonmies,我在编辑中添加了这些信息,非常感谢您的关注,构建全局还需要其他什么吗?我已经为此挣扎了好几天了!首先,我要感谢你全面的回答,我已经迫不及待地等待了。让我像你那样逐点回答你:1.1。使用LU或Cholesky预处理的目的是最小化迭代次数,因此较少的迭代次数是预处理的一个特点,并且应针对此类情况优化解算器。1.2。我已经将我的代码与许多功能强大的CPU版本MKL以及我们公司编写的其他代码进行了对比,CG的对角缩放预处理版本在GPU上更快,而LU预处理版本则慢得多。2.1。我读过naumov博士的论文,其中描述了如何构造LU或Cholesky分解,但是根据cUSparse的最新文档,没有创建预条件的函数,但是请告诉我,如果有,这将非常有用。进行这样的测试并发布它们将是非常好的。我不明白马克西姆博士如何看待MKL的胜利阶段,如果他用一个1300美元的特斯拉C2050来对抗300美元的英特尔I7 950,我猜这个比较是不公平的,而且,如果解决阶段被重复多次,那么加速增益会被获得,在某些情况下这可能是很高的。而预处理通常需要减少迭代次数