scalapack中的行分配不一致

问题描述 投票:0回答:1

考虑以下简单的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

这就说不通了,为什么在块大小为100的情况下,行列0会得到200个元素,而行列*块大小> N.正因为如此,我的程序在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

fortran mpi lapack scalapack
1个回答
2
投票

你的代码有很多错误的地方

1)首先不要使用Integer( 8 )。就像Vladimir说的那样,请不要学这个。它不仅不具有可移植性,因此是非常糟糕的做法(请看这里的许多例子,例如。Fortran 90 kind参数)在这里它是错误的,因为 numroc 期待一个默认的整数作为它的第一个参数(例如,见 https:/software.intel.comcontentwwwusendevelopdocumentationmkl-developer-reference-fortrantopscalapack-routinesscalapack-utility-functions-and-routinesnumroc.html。)

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

3) 你误解了MPI_Dims_create。你似乎认为你会得到一个一维的分布,但实际上你要求它得到一个二维的分布。引用标准中的一句话 https:/www.mpi-forum.orgdocsmpi-3.1mpi31-report.pdf

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

你设置dims等于0,所以例程可以自由设置两个维度。因此对于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个进程--你会看到一个奇数的进程,根据你的说法是 "不工作",这是因为(高级数学提醒)15=3x5。顺便说一下,在我的机器上,9个进程并没有返回3x3--这在我看来是openmpi的一个错误。

© www.soinside.com 2019 - 2024. All rights reserved.