petsc_solver优化
编译petsc_solver
1 |
|
cmakelists.txt
1 | cmake_minimum_required(VERSION 3.1) |
优化一:
export CC=mpiicx
export CXX=mpiicpx
显示指定了编译器为mpiicx和mpiicpx
优化二:
1 | # 设置为 Release 模式,并启用优化选项 |
优化三:
使用PetscMalloc1和PetscFree等petsc自带的方法管理内存,确保与 PETSc 的内存管理机制兼容。
源代码
1 | start = MPI_Wtime(); // 开始记录解耦部分的时间 |
优化后的代码如下
1 | //////////////////////////////////////////////////////////////////// |
移除了重复内存分配的部分:
在原代码中,对于
globalx
和globaly
这两个指针的内存分配是通过malloc
实现的,而在优化后代码中,这些内存是使用PetscMalloc1
分配的,这样可以更好地整合 PETSc 自己的内存管理,提高内存分配和释放的性能。原代码中使用了
int *globalx = (int *)malloc(blockSize * sizeof(int))
和int *globaly = (int *)malloc(blockSize * sizeof(int))
,而在第二段代码中替换为ierr = PetscMalloc1(blockSize, &globalx)
和ierr = PetscMalloc1(blockSize, &globaly)
,并且这些内存通过PetscFree
进行释放,确保与 PETSc 的内存管理机制兼容。
重复计算的减少:
在优化后的代码中,循环中预计算了
rowBase
变量,这减少了在每次循环中重复进行的乘法运算:1
int rowBase = (Ii + Istart) * blockSize;
- 这一优化避免了在循环内多次计算
rowBase
,提高了性能,特别是在循环次数较多时。
- 这一优化避免了在循环内多次计算
代码的组织更加结构化:
- 优化后的代码将
globalx
和globaly
的赋值与矩阵A
的值的填充更加结构化,使代码逻辑清晰,更易于维护和理解。
- 优化后的代码将
内存释放管理的改进:
优化后的代码使用
PetscFree
函数显式释放内存,这样可以与 PETSc 的内存管理体系保持一致,减少内存泄漏的风险。例如:
1
2
3
4
5
6ierr = PetscFree(globalx);
CHKERRQ(ierr);
ierr = PetscFree(globaly);
CHKERRQ(ierr);
ierr = PetscFree(bIndex);
CHKERRQ(ierr);而在原代码中则没有对
globalx
和globaly
进行显式的释放。
代码的错误检查:
- 优化后的代码在执行内存分配、矩阵和向量创建等操作后,通过
CHKERRQ(ierr)
检查错误,提高了代码的鲁棒性,使得在出现错误时更容易定位问题。
- 优化后的代码在执行内存分配、矩阵和向量创建等操作后,通过
可以继续尝试的可能
矩阵和向量的重用:对于多次重复使用的矩阵 A
和向量 b
,可以考虑将它们保留并复用,而不是每次都重新创建,这样可以减少初始化的开销。
并行化内存初始化:在对 nDCount
和 nNDCount
进行初始化时,可以考虑并行化这部分代码,利用 OpenMP 或 MPI 实现并行加速,从而加快初始化速度。
进一步的内存对齐和缓存优化:考虑到 globalx
和 globaly
数组可以频繁访问,可以使用内存对齐来优化它们在 CPU 缓存中的使用,利用指令集提供的对齐内存分配,例如使用 _mm_malloc()
。
批量设置矩阵值:使用 PETSc 的批量操作 MatSetValuesBlocked
来设置矩阵值,可以减少函数调用次数,提高整体性能。
同时PETSc中集成了与GPU加速线性求解器的接口
在编译PETSc时,使用 ./configure --with-cuda=1 --with-cudac=/usr/local/cuda/bin/nvcc
,这样可以让PETSc支持CUDA,并且与GPU进行集成。
代码修改:
在PETSc代码中,将向量类型设置为CUDA:
1
2cpp复制代码VecCreate(PETSC_COMM_WORLD, &x);
VecSetType(x, VECCUDA);设置矩阵类型为CUDA:
1
2cpp复制代码MatCreate(PETSC_COMM_WORLD, &A);
MatSetType(A, MATAIJCUDA);这些修改将确保PETSc将矩阵和向量的操作放在GPU上执行。
预处理器和求解器设置:
设置求解器使用GPU加速:
1
2
3
4
5bash
复制代码
-pc_type hypre -pc_hypre_type boomeramg -pc_hypre_boomeramg_relax_type_all symmetric-SOR/Jacobi -pc_hypre_boomeramg_interp_type ext+i -ksp_type gmres这些选项会使用Hypre的BoomerAMG预处理器,并在GPU上进行加速。
开启cuda加速
1 | //////////////////////////////////////////////////////////////////// |
在查阅PETSc文档后,确定了Mat, Vector, Ksp等PETSc变量可以被重复利用的前提下,可以将其改变为静态类型变量,得到进一步的性能提升,但是可惜的是并没有观察到有效的变化,估计是编译器做了一些神奇的优化掩盖掉了。(o3魅力时刻了说是)