F90代码替换MPI_Allgather为MPI_Allgatherv出现段错误求指导
解决MPI_Allgather替换为MPI_Allgatherv的段错误问题
要处理各进程向量长度不一致的情况,MPI_Allgatherv需要明确每个进程的发送/接收计数,以及接收缓冲区的位移参数。以下是针对你的Fortran代码的修改方案:
关键步骤说明
- 先通过
MPI_Allgather收集所有进程的nnodes值,让每个进程都能知晓其他进程的数据长度 - 基于收集到的
nnodes数组,计算每个进程对应的接收计数(recvcounts),即每个进程要发送的double类型元素总数:nnodes * ndim - 计算接收位移数组(
displs),用于指定每个进程的数据在接收缓冲区中的起始位置,位移值为前面所有进程的元素总数之和
修改后的完整代码
use mpi ! 确保已引入MPI模块 implicit none ! 假设nodes、ndim、zero等变量已提前声明 integer :: nnodes, nnodes_all, ierr, ct, i, j, rank, nprocs integer, allocatable :: recvcounts_nnodes(:), recvcounts(:), displs(:) double precision, allocatable :: nxyz1(:), nxyz_gather1(:), nxyz2(:,:) ! 获取当前进程rank和总进程数 call mpi_comm_rank(mpi_comm_world, rank, ierr) call mpi_comm_size(mpi_comm_world, nprocs, ierr) nnodes = size(nodes) nnodes_all = 0 call mpi_allreduce(nnodes, nnodes_all, 1, MPI_INTEGER, MPI_SUM, mpi_comm_world, ierr) ! 分配存储各进程nnodes的数组 allocate(recvcounts_nnodes(nprocs)) call mpi_allgather(nnodes, 1, MPI_INTEGER, recvcounts_nnodes, 1, MPI_INTEGER, mpi_comm_world, ierr) ! 计算接收计数和位移数组 allocate(recvcounts(nprocs), displs(nprocs)) recvcounts = recvcounts_nnodes * ndim displs(1) = 0 do i = 2, nprocs displs(i) = displs(i-1) + recvcounts(i-1) end do allocate(nxyz1(nnodes*ndim)) allocate(nxyz_gather1(nnodes_all*ndim)) allocate(nxyz2(nnodes_all, ndim)) nxyz1 = zero; nxyz_gather1 = zero; nxyz2 = zero ct = 1 do i = 1, size(nodes) do j = 1, ndim nxyz1(ct) = nodes(i) % xyz(j) ct = ct + 1 end do end do ! 替换为MPI_Allgatherv call mpi_allgatherv(nxyz1, nnodes*ndim, MPI_DOUBLE, & nxyz_gather1, recvcounts, displs, MPI_DOUBLE, & mpi_comm_world, ierr) ! 释放临时数组 deallocate(recvcounts_nnodes, recvcounts, displs)
代码解释
recvcounts_nnodes:存储每个进程的nnodes值,通过MPI_Allgather实现全局同步recvcounts:每个进程需要发送的double元素数量,等于nnodes * ndimdispls:接收缓冲区中每个进程数据的起始索引(以元素为单位,不是字节),Fortran数组从1开始,所以第一个位移设为0MPI_Allgatherv参数顺序:发送缓冲区、发送计数、发送类型、接收缓冲区、接收计数数组、位移数组、接收类型、通信域、错误码
内容的提问来源于stack exchange,提问作者Haoran Shi
相关产品推荐
相关产品推荐

