Fortran scalapack中的行分配不一致

Fortran scalapack中的行分配不一致,fortran,mpi,lapack,scalapack,Fortran,Mpi,Lapack,Scalapack,考虑以下简单的fortran程序 program test_vec_allocation use mpi implicit none integer(kind=8) :: N ! =========================BLACS and MPI======================= integer :: ierr, size, rank,dims(2) ! ----

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

头皮包版本:2.1.0


MacOS版本:10.11

您的代码有许多问题

1) 首先,不要使用整数(8)。正如弗拉基米尔所说,请忘记这一点。它不仅不可移植,因此是非常糟糕的做法(请参见此处的许多示例,例如)。这里它是错误的,因为
numroc
期望默认类型的整数作为其第一个参数(参见示例)

2) 在调用MPI_Init之前调用一个MPI例程,其中包含大量异常(这不是一个),这会导致未定义的行为。注意,处的描述没有提及实际调用MPI_Init。因此,我也更喜欢称MPI_为Finalize

3) 您误解了MPI\u Dims\u创建。你似乎假设你会得到一维分布,但实际上你要求得到二维分布。从标准中引用

数组DIM中的条目被设置为描述笛卡尔网格 具有ndims维度,共有nnodes节点。尺寸是 设置为尽可能靠近彼此,使用适当的 整除算法。调用者可以进一步约束调用 通过指定数组DIM的元素来操作此例程。如果 dims[i]设置为正数时,例程不会修改 维度i中的节点数;仅限dims[i]=0的条目 由调用修改


将dims设置为零,因此例程可以自由设置两个尺寸。因此,对于11个进程,您将得到一个1x11或11x1网格,这似乎是您所期望的。但是,对于12个过程,由于
尺寸设置为尽可能彼此接近
您将获得3x4或4x3网格,而不是12x1。如果每行的值为3x4,您希望
numroc
返回3个进程,包含200个元素(2个块),1个进程包含100个元素。由于有3行,因此您希望3x3=9个进程返回200,3x1=3个进程返回100。这就是你看到的。也可以尝试15个进程-你会看到奇数个进程,根据你的说法“不起作用”,这是因为(高等数学警报)15=3x5。顺便说一句,在我的机器上,9进程没有返回3x3-在我看来,这就像openmpi中的一个错误。

您的代码有很多地方出错

1) 首先,不要使用整数(8)。正如弗拉基米尔所说,请忘记这一点。它不仅不可移植,因此是非常糟糕的做法(请参见此处的许多示例,例如)。这里它是错误的,因为
numroc
期望默认类型的整数作为其第一个参数(参见示例)

2) 在调用MPI_Init之前调用一个MPI例程,其中包含大量异常(这不是一个),这会导致未定义的行为。注意,处的描述没有提及实际调用MPI_Init。因此,我也更喜欢称MPI_为Finalize

3) 您误解了MPI\u Dims\u创建。你似乎假设你会得到一维分布,但实际上你要求得到二维分布。从标准中引用

数组DIM中的条目被设置为描述笛卡尔网格 具有ndims维度,共有nnodes节点。尺寸是 设置为尽可能靠近彼此,使用适当的 整除算法。调用者可以进一步约束调用 通过指定数组DIM的元素来操作此例程。如果 dims[i]设置为正数时,例程不会修改 维度i中的节点数;仅限dims[i]=0的条目 由调用修改


将dims设置为零,因此例程可以自由设置两个尺寸。因此,对于11个进程,您将得到一个1x11或11x1网格,这似乎是您所期望的。但是,对于12个过程,由于
尺寸设置为尽可能彼此接近
您将获得3x4或4x3网格,而不是12x1。如果每行的值为3x4,您希望
numroc
返回3个进程,包含200个元素(2个块),1个进程包含100个元素。由于有3行,因此您希望3x3=9个进程返回200,3x1=3个进程返回100。这就是你看到的。也可以尝试15个进程-你会看到奇数个进程,根据你的说法“不起作用”,这是因为(高等数学警报)15=3x5。顺便说一句,在我的机器上,9进程没有返回3x3-这在我看来像openmpi中的一个错误。

感谢您的见解,我使用MPI_Dims_create获取blacs_gridinit的nprow和npcol。你能指出一个我能以正确的方式实现相同功能的来源吗?这也为我的第二个问题铺平了道路,我想做一个矩阵向量乘法,然后计算范数并确定它,问题是那些没有分配向量元素的节点的范数为0.0000,因此测试失败。我应该修改当前问题还是询问其他问题?请您也提供意见好吗?
请致电pdnrm2(N,norm,tmp_vec,1,1,descvec,1);如果(标准基本上在上述对pdnrm2的调用中,将0.000分配给其他行中的非参与进程。但是,在11个等级等情况下,norm被正确分配给非参与节点。如果您有单独的问题,请将其放在单独的问题中。如果您想要1*nproc网格,为什么需要调用mpi_dims_create?创建的所有mpi dims都会找到合适的f