使用MPI_TYPE_VECTOR而不是MPI_GATHER

时间:2016-02-06 20:52:33

标签: parallel-processing fortran openmpi

假设 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

1 个答案:

答案 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。