Я написал решатель Conjugate-gradient (для линейной системы уравнений) с предварительной обработкой LU, я использовал документы в исследовательском сообществе nvidia в качестве руководства, этап обновления остатков, который требует решения системы нижней треугольной матрицы, а затем решения системы верхней треугольной матрицы, разделен на две фазы. :
- фаза анализа (которая использует шаблон разреженности и определяет уровень параллелизации).
- сам этап решения.
согласно всем сообщениям, связанным с этой темой, и самой статье Наумова, фаза анализа значительно медленнее, чем фаза решения, но выполняется один раз, поэтому это не должно быть проблемой, если принять во внимание все время выполнения, однако, в моей программе фаза анализа требует ~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() ;
Итак, кто-нибудь понял, почему фаза анализа такая медленная? и как его можно ускорить? зависит ли (время выполнения фазы анализа)/(время выполнения фазы решения) ratio от GPU?
Редактировать: я пробовал этот решатель во многих случаях, и результаты были близки, но в конкретном случае, который меня беспокоит, он имеет следующие условия:
- Размер (N): ~860 000 * 860 000
- Количество ненулевых значений (Новая Зеландия): ~6 000 000
- Количество итераций, необходимых для сходимости: 10
- Время выполнения фазы Анализ: 210 мс
- Время выполнения фазы решения (сумма всех итераций): 350 мс
- Все операции с плавающей запятой выполняются в формате двойной точности.
- Графический процессор: GeForce GTX 550 Ti
- ОС: Windows 7 максимальная, 64-разрядная