Parallel processing 使用MPI_类型_向量而不是MPI_聚集
假设k进程计算矩阵a的元素,其维数为(n,m),其中n是行数,m是列数。我试图使用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
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