0

考虑以下简单的 fortran 程序

program test_vec_allocation
    use mpi
    implicit none
    integer(kind=8)             :: N
    ! =========================BLACS and MPI=======================
    integer                     :: ierr, size, rank,dims(2)
    ! -------------------------------------------------------------
    integer, parameter          :: block_size = 100
    integer                     :: context, nprow, npcol, local_nprow, local_npcol
    integer                     :: numroc, indxl2g, descmat(9),descvec(9)
    integer                     :: mloc_mat ,nloc_mat ,mloc_vec ,nloc_vec

    call blacs_pinfo(rank,size)
    dims=0
    call MPI_Dims_create(size, 2, dims, ierr)
    nprow = dims(1);npcol = dims(2)
    call blacs_get(0,0,context)
    call blacs_gridinit(context, 'R', nprow, npcol)
    call blacs_gridinfo(context, nprow, npcol, local_nprow,local_npcol)

    N = 700

    mloc_vec = numroc(N,block_size,local_nprow,0, nprow)
    nloc_vec = numroc(1,block_size,local_npcol,0, npcol)
    print *,"Rank", rank, mloc_vec, nloc_vec

    call blacs_gridexit(context)
    call blacs_exit(0)

end program test_vec_allocation

当我以 11 mpi 等级运行它时,我得到

 Rank           0         100           1
 Rank           4         100           1
 Rank           2         100           1
 Rank           1         100           1
 Rank           3         100           1
 Rank          10           0           1
 Rank           6         100           1
 Rank           5         100           1
 Rank           9           0           1
 Rank           8           0           1
 Rank           7           0           1

这就是我期望 scalapack 划分这个数组的方式,但是,对于我得到的偶数等级:

 Rank           0         200           1
 Rank           8         200           0
 Rank           9         100           1
 Rank          10         100           0
 Rank           1         200           0
 Rank           6         200           1
 Rank          11         100           0
 Rank           3         200           1
 Rank           4         200           0
 Rank           2         200           0
 Rank           7         200           0
 Rank           5         200           0

这没有任何意义,为什么排名 0 会为块大小 100 和排名 * 块大小 > N 获得 200 个元素。因此,我的程序适用于 mpi 排名 1、2、3、5、7、11,但对于排名 4 则失败,6,8,9,10,12 等(我不知道为什么它在 9 级时失败了!)。谁能解释我的方法有什么问题?

GFortran 版本:6.1.0

SCALPACK 版本:2.1.0

macOS 版本:10.11

4

1 回答 1

2

您的代码有很多问题

1)首先不要使用整数(8)。正如弗拉基米尔所说,请忘记这一点。它不仅不可移植,因此非常糟糕的做法(请参阅此处的许多示例,例如Fortran 90 种类参数),这是错误的,因为numroc期望将默认种类的整数作为其第一个参数(参见例如https://software.intel。 com/content/www/us/en/develop/documentation/mkl-developer-reference-fortran/top/scalapack-routines/scalapack-utility-functions-and-routines/numroc.html

2)在调用 MPI_Init 之前调用 MPI 例程,手上充满了异常(这不是一个),这会导致未定义的行为。请注意https://www.netlib.org/blacs/BLACS/QRef.html#BLACS_PINFO的描述并没有提及实际调用 MPI_Init。因此,我也更喜欢调用 MPI_Finalise

3) 你误解了 MPI_Dims_create。您似乎假设您将获得一维分布,但实际上您要求它提供二维分布。引用https://www.mpi-forum.org/docs/mpi-3.1/mpi31-report.pdf的标准

数组 dims 中的条目设置为描述具有 ndims 维度和总共 nnodes 个节点的笛卡尔网格。使用适当的可分性算法将维度设置为尽可能接近。调用者可以通过指定数组 dims 的元素来进一步限制该例程的操作。如果 dims[i] 设置为正数,则例程不会修改维度 i 的节点数;只有那些 dims[i] = 0 的条目被调用修改。

您将 dims 设置为零,因此该例程可以自由设置两个维度。因此,对于 11 个进程,您将获得 1x11 或 11x1 网格,这正是您所期望的。但是对于 12 个进程,The dimensions are set to be as close to each other as possible您将获得 3x4 或 4x3 网格,而不是 12x1。如果每行是 3x4,则您希望numroc返回 3 个具有 200 个元素(2 个块)的进程,以及 1 个具有 100 个元素的进程。由于有 3 行,因此您期望 3x3=9 进程返回 200,3x1=3 返回 100。这就是你看。还要尝试 15 个 proc - 你会看到奇数个进程,根据你的说法“不起作用”,这是因为(高级数学警报)15 = 3x5。顺便说一句,在我的机器上,9 个进程不会返回 3x3 - 这对我来说就像 openmpi 中的一个错误。

于 2020-05-12T08:48:56.190 回答