Parallel processing 使用MPI_类型_向量而不是MPI_聚集

Parallel processing 使用MPI_类型_向量而不是MPI_聚集,parallel-processing,fortran,openmpi,Parallel Processing,Fortran,Openmpi,假设k进程计算矩阵a的元素,其维数为(n,m),其中n是行数,m是列数。我试图使用MPI_GATHER将这两个矩阵收集到根进程中的矩阵B,其中B的维数为(n,km)。更具体地说,我在下面编写了一个fortran代码示例。这里,我将矩阵A(不是整个矩阵)的列传递给矩阵B,但这不起作用。当我使用mpirun-n 2 a.out运行可执行文件时,我得到错误: malloc:**对象0x7ffa89413fb8的错误:已释放对象的校验和不正确-对象可能在被释放后被修改 1) 为什么我会收到此错误消息 2

假设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类型向量

3) 我应该如何更正代码的
MPI\u聚集
部分?我能通过整个矩阵A吗


有两种类型的聚集操作可以在二维数组中执行。 1.从所有流程的维度2收集元素,并将其收集到一个流程的维度2中;和 2.从所有流程的维度2收集元素,并将其收集到一个流程的维度1中

在这个例子中说,; n=dimension-1和m=dimension-2,我们知道Fortran是主要列。因此,在Fortran中,维1在内存中是连续的

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

如下所示的单个MPI_Gather调用将获得所需的操作,而无需任何如上所示的循环技巧:

调用MPI\u聚集(A,n*(m/NUM\u PROC),MPI\u整数&
B、 n*(m/NUM\u PROC),MPI\u整数,主ID&
MPI_COMM_WORLD,IERROR)

但是,如果您试图在MASTER_ID proc中从Array-A的维2到Array-B的维1的所有进程中收集元素,则此时我们需要使用MPI_TYPE_VECTOR,在这里我们使用非连续元素创建一个新类型。让我知道你的意图


因为,当前的代码逻辑看起来不需要使用MPI类型向量。

谢谢,这是一个非常清晰的解释!
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