考虑以下简单的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
你的代码有很多错误的地方
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的一个错误。