使用 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。
假设 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。