PETSc代码单进程运行正常,双进程崩溃的原因求助
问题分析与解决方案
问题根源
当以双进程模式运行时,PETSc会将总大小为1的分布式向量自动划分:其中一个进程的向量局部大小为0,另一个进程的局部大小为1。但原代码中的FormFunction函数未检查当前进程的向量局部大小,直接访问ax[0]和aF[0],局部大小为0的进程会因内存越界触发段错误(SEGV)。
修复方案
在计算残差前,先获取当前进程的向量局部大小,仅当局部存在元素时执行计算逻辑;无元素的进程直接跳过操作。
修改后的FormFunction函数
PetscErrorCode FormFunction(SNES snes, Vec x, Vec F, void *ctx) { PetscErrorCode ierr; const PetscReal *ax; PetscReal *aF; PetscInt local_size; // 获取当前进程的向量局部大小 ierr = VecGetLocalSize(x, &local_size); CHKERRQ(ierr); if (local_size == 0) return 0; // 无局部元素,直接返回 ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr); ierr = VecGetArray(F,&aF);CHKERRQ(ierr); aF[0] = atan(ax[0]); ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr); ierr = VecRestoreArray(F,&aF);CHKERRQ(ierr); return 0; }
可选优化:显式指定向量局部大小
如果确定问题仅涉及单元素向量,也可以在创建向量时直接指定每个进程的局部大小,避免自动划分导致的局部大小为0的情况:
// 替换原VecSetSizes调用 PetscMPIInt rank; MPI_Comm_rank(PETSC_COMM_WORLD, &rank); ierr = VecSetSizes(x, (rank == 0) ? 1 : 0, 1); CHKERRQ(ierr);
不过第一种方案更通用,适用于任意大小的分布式向量。
验证结果
修改后执行双进程命令:
~/petsc/arch-darwin-c-opt/bin/mpiexec -n 2 ./atan -snes_fd
将正常输出结果,无段错误。
内容的提问来源于stack exchange,提问作者Eder Lima de Albuquerque
相关产品推荐
相关产品推荐

