【发布时间】:2016-09-28 08:05:25
【问题描述】:
假设一个程序在xp 次yp 次zp 进程上运行。
使用笛卡尔通信器,可以认为进程被安排在维度 (xp,yp,zp) 的网格中。
在这个程序中,根进程 (0) 声明并分配了一个 3D 数组 Atot,它将由每个进程(包括根)声明的 3D 数组 A 填充。
INTEGER, DIMENSION(3) :: Ntot
INTEGER, DIMENSION(3) :: N
INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: Atot
INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: A
:
! the 3 elements of the array N are determined by dividing the corresponding
! element of the array Ntot by the number of process in that direction
! taking into account the reminder of the division.
:
IF (myid == 0) THEN ! myid is the process' rank
ALLOCATE(Atot(Ntot(1),Ntot(2),Ntot(3))
END IF
ALLOCATE(A(N(1),N(2),N(3))
A = myid
哪种方式是最正确、最简单、最有效的沟通方式?
我在考虑MPI_gather:每个进程都会发送由N(1)*N(2)*N(3)MPI_INTEGERs 组成的整个数组A,然后根进程应该将它们接收到对应于多维数据集的单个MPI 派生数据类型中(MPI_type_vector 应该递归使用两次,对吗?)。
可以吗?
即使这样可行,当笛卡尔通信器的每个方向上的进程数均分Ntot 的相应元素时,对我来说听起来很容易,即当数组A 在每个方向上具有相同的维度时过程。 Ntot = (/9,9,9/) 时就是这种情况。
Ntot = (/10,10,10/)的案子呢? mpi派生的数据类型在不同的进程中会有不同的维度,那么是否仍然可以使用MPI_ghather?
编辑
我不排除 MPI_GATHERV 可能是解决方案的一部分。但是,它允许每个进程发送(和根进程接收)不同数量的数据,即不同数量的 MPI_INTEGERS(在简单示例中)。然而,在我正在处理的情况下,根进程必须接收 3 维数组Atot 中的数据。为此,我认为定义 MPI 派生数据类型可能很有用,我们将其命名为 smallcube。在这种情况下,每个进程发送整个数组A,而主进程将从每个进程接收1 个smallcube 类型的数据。关键是small cube在三个维度上的长度不同,具体取决于它在笛卡尔网格中的位置(假设长度不均匀地除以三个维度上的进程数)。
【问题讨论】:
-
如果我错了就更正,但我认为 MPI_GATHERV(注意 V)允许每个进程的数据数量不同,也许这就是您在问题的最后一部分中寻找的内容?
-
我编辑了问题:)
-
这可以通过使用
MPI_ALLTOALLW来模拟不存在的MPI_SCATTERW来实现。 Jonathan Dursi here (也包括MPI_ALLTOALLW方法)为 C 提供了另一种规范答案。希望你能理解它的工作原理并将其翻译成 Fortran(这样做应该相对简单)。如果在那之前没有其他人会这样做,我可以在我有更多空闲时间时这样做。 -
为什么要这样做?如果是将数据写入文件,MPI-IO 几乎肯定是一种更好的方法。我问,因为复制整个分布式对象几乎总是不是一个好主意,即使只是出于内存使用的原因
-
无论您使用诸如 MPI_Scatterv 还是 MPI-IO 之类的集合,MPI_Type_create_subarray 是迄今为止最简单的方法 - 您会认为递归使用 MPI_Type_vector 会起作用,但由于类型范围的问题,它非常棘手。 archer.ac.uk/training/course-material/2015/12/ParallelIO_Oxford/… 的 IO 基准测试代码展示了如何使用 MPI-IO 从 Fortran 编写 3D 数组。
标签: arrays multidimensional-array fortran mpi