使用 MPI_TYPE_VECTOR 而不是 MPI_GATHER

Using MPI_TYPE_VECTOR instead of MPI_GATHER

假设 k 进程计算矩阵 A 的元素,其维度为 (n,m) ,其中 n 是行数,m 是列数。我正在尝试使用 MPI_GATHER 将这两个矩阵聚集到根进程的矩阵 B 中,其中 B 的维度是(n,km)。更具体地说,我在下面写了一个示例 fortran 代码。在这里,我将矩阵 A (不是整个矩阵)的列传递给矩阵 B 但这行不通。当我 运行 使用 mpirun -n 2 a.out 的可执行文件时,我收到错误:

malloc:对象 0x7ffa89413fb8 的 *** 错误:释放对象的校验和不正确 - 对象可能在释放后被修改。

1) 为什么我会收到此错误消息?

2) 谁能从概念上解释一下,为什么我要用MPI_TYPE_VECTOR

3) 我应该如何更正代码的 MPI_GATHER 部分?我可以传递整个矩阵[​​=27=]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

可以在二维数组中执行两种类型的收集操作。 1、将所有进程的维度2的元素汇集到一个进程的维度2;和 2. 将所有进程的维度2的元素汇集到一个进程的维度1。

在这个例子中表示; n=dimension-1,m=dimension-2,我们知道Fortran是column major。因此,维度 1 在 Fortran 中的内存中是连续的。

在您的收集语句中,您试图从所有进程中收集 Array-A 的第 2 维,并将其收集到 MASTER_ID proc(TYPE-1) 中的 Array-B 的第 2 维中.由于 dimension-2 在内存中是不连续的,这会导致分段错误。

如下所示的单个 MPI_Gather 调用将到达所需的操作,没有任何循环技巧,如上所示:

CALL MPI_GATHER(A, n*(m/NUM_PROC), MPI_INTEGER, & B, n*(m/NUM_PROC), MPI_INTEGER, MASTER_ID, & MPI_COMM_WORLD, IERROR)

但是,如果你试图在MASTER_ID proc中从Array-A的dimension-2收集元素到Array-B的dimension-1,这时我们需要利用MPI_TYPE_VECTOR,我们在其中创建具有非连续元素的新类型。让我知道这是否是意图。

因为,目前的代码逻辑看起来并不需要利用MPI_TYPE_VECTOR。