假设 k 进程计算矩阵 A 的元素,其维度为(n,m),其中 n 是行数, m 是列数。我正在尝试使用MPI_GATHER
将这两个矩阵收集到根进程中的矩阵 B ,其中 B 的维度为(n,公里)。更具体地说,我在下面写了一个示例fortran代码。在这里,我将矩阵 A (而不是整个矩阵)的列传递给矩阵 B ,但这不起作用。当我使用mpirun -n 2 a.out
运行可执行文件时,我收到错误:
malloc:***对象0x7ffa89413fb8的错误:释放对象的校验和不正确 - 对象可能在被释放后被修改。
1)为什么我收到此错误消息?
2)谁可以在概念上解释 ,为什么我必须使用MPI_TYPE_VECTOR
?
3)我应该如何更正代码的MPI_GATHER
部分?我可以通过整个矩阵 A 吗?
PROGRAM test
IMPLICIT NONE
INCLUDE "mpif.h"
INTEGER, PARAMETER :: n=100, m=100
INTEGER, ALLOCATABLE, DIMENSION(:,:) :: A
INTEGER, DIMENSION(n,m) :: B
INTEGER :: ind_a, ind_c
INTEGER :: NUM_PROC, PROC_ID, IERROR, MASTER_ID=0
INTEGER :: c
INTEGER, DIMENSION(m) :: cvec
CALL MPI_INIT(IERROR)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, PROC_ID, IERROR)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, NUM_PROC, IERROR)
ALLOCATE(A(n,m/NUM_PROC))
DO ind_c=1,m
cvec(ind_c)=ind_c
END DO
! Fill in matrix A
DO ind_a=1,n
DO ind_c=1,m/NUM_PROC
c=cvec(ind_c+PROC_ID*m/NUM_PROC)
A(ind_a,ind_c)=c*ind_a
END DO
END DO
! Gather the elements at the root process
DO ind_a=1,n
CALL MPI_GATHER(A(ind_a,:),m/NUM_PROC,MPI_INTEGER,B(ind_a,PROC_ID*m/NUM_PROC+1:(PROC_ID+1)*m/NUM_PROC),m/NUM_PROC,MPI_INTEGER,MASTER_ID,MPI_COMM_WORLD,IERROR)
END DO
CALL MPI_FINALIZE(IERROR)
END PROGRAM
答案 0 :(得分:1)
有两种类型的聚集操作可以在二维数组中执行。 1.从所有过程的第2维收集元素并将其收集在一个过程的维度-2中;和 2.从所有过程的第2维收集元素,并将其收集在一个过程的维度-1中。
在这个例子中说; n =维度-1,m =维度-2,我们知道Fortran是列专业。因此,维度1在Fortran的内存中是连续的。
在您的collect语句中,您尝试从所有进程中收集Array-A的dimension-2,并将其收集到MASTER_ID proc(TYPE-1)中Array-B的dimension-2中。因为,维度2在内存中是非连续的,这会导致分段错误。
如下所示,单个MPI_Gather调用将进入所需的操作,没有任何循环技巧,如上所示:
:crypto.strong_rand_bytes(12)
但是,如果您尝试将Array-A的dimension-2中的元素从所有进程收集到MASTER_ID proc中的Array-B的dimension-1,那么当我们需要使用MPI_TYPE_VECTOR时,我们创建一个具有非连续元素的新类型。让我知道这是不是意图。
因为,当前的代码逻辑看起来不像我们需要使用MPI_TYPE_VECTOR。