'MPI_Barrier' 和 'BLACS_Barrier' 都不会阻止处理器执行其命令
Niether 'MPI_Barrier' nor 'BLACS_Barrier' doesn't stop a processors executing its commands
我正在研究 ScaLAPACK 并尝试适应使用 ScaLAPACK 必不可少的 BLACS 例程。
我上过一些关于 MPI 的初级课程,所以对 MPI_COMM_WORLD 的东西有一些粗略的了解,但对它的内部工作原理等没有深入的了解。
无论如何,我正在尝试按照代码使用 BLACS 例程打招呼。
program hello_from_BLACS
use MPI
implicit none
integer :: info, nproc, nprow, npcol, &
myid, myrow, mycol, &
ctxt, ctxt_sys, ctxt_all
call BLACS_PINFO(myid, nproc)
! get the internal default context
call BLACS_GET(0, 0, ctxt_sys)
! set up a process grid for the process set
ctxt_all = ctxt_sys
call BLACS_GRIDINIT(ctxt_all, 'c', nproc, 1)
call BLACS_BARRIER(ctxt_all, 'A')
! set up a process grid of size 3*2
ctxt = ctxt_sys
call BLACS_GRIDINIT(ctxt, 'c', 3, 2)
if (myid .eq. 0) then
write(6,*) ' myid myrow mycol nprow npcol'
endif
(**) call BLACS_BARRIER(ctxt_sys, 'A')
! all processes not belonging to 'ctxt' jump to the end of the program
if (ctxt .lt. 0) goto 1000
! get the process coordinates in the grid
call BLACS_GRIDINFO(ctxt, nprow, npcol, myrow, mycol)
write(6,*) 'hello from process', myid, myrow, mycol, nprow, npcol
1000 continue
! return all BLACS contexts
call BLACS_EXIT(0)
stop
end program
'mpirun -np 10 ./exe' 的输出就像
hello from process 0 0 0 3 2
hello from process 4 1 1 3 2
hello from process 1 1 0 3 2
myid myrow mycol nprow npcol
hello from process 5 2 1 3 2
hello from process 2 2 0 3 2
hello from process 3 0 1 3 2
除了我在代码左侧标记 (**) 的 'BLACS_BARRIER' 行外,一切似乎都正常。
我已经放置了该行以生成如下所示的输出,其标题行始终打印在它的顶部。
myid myrow mycol nprow npcol
hello from process 0 0 0 3 2
hello from process 4 1 1 3 2
hello from process 1 1 0 3 2
hello from process 5 2 1 3 2
hello from process 2 2 0 3 2
hello from process 3 0 1 3 2
那么问题来了,
我试过BLACS_BARRIER到'ctxt_sys'、'ctxt_all'和'ctxt',但它们都没有输出标题行首先打印。我也试过 MPI_Barrier(MPI_COMM_WORLD,info),但也没用。我是不是用错了障碍?
另外,我在使用BLACS_BARRIER到'ctxt'时得到了SIGSEGV,并且在执行mpirun时使用了6个以上的进程。为什么在这种情况下会发生 SIGSEGV?
感谢您阅读这个问题。
回答你的2个问题(以后最好分开发帖)
1) MPI_Barrier、BLACS_Barrier 以及我遇到的任何并行编程方法中的任何障碍只会同步调用它的实际进程集。然而 I/O 并不仅仅由调用进程处理,而是至少在 OS 中处理 I/O 中的一个,并且很可能更多,它实际上处理 I/O 请求。这些不是由您的屏障同步的。因此 I/O 的排序不能通过简单的屏障来保证。我能想到的确保 I/O 排序的唯一符合标准的方法是
- 让 1 个进程完成所有 I/O 或
- 更好的方法是直接或间接使用 MPI I/O,例如通过NetCDF 或 HDF5
2) 您第二次致电 BLACS_GRIDINIT
call BLACS_GRIDINIT(ctxt, 'c', 3, 2)
为 3 x 2 进程网格创建上下文,因此包含 6 个进程。如果你用超过 6 个进程调用它,只有 6 个将被 return 编辑为有效的上下文,对于其他 ctxt
应该被视为未初始化的值。因此,例如,如果您使用 8 个进程调用它,则 6 个将 return 具有有效的 ctxt
,2 个将 return 具有 ctxt
没有有效值。如果这 2 个现在尝试使用 ctxt
任何事情都是可能的,在你的情况下你会遇到段错误。你似乎确实看到这是一个问题,因为后来你有
! all processes not belonging to 'ctxt' jump to the end of the program
if (ctxt .lt. 0) goto 1000
但我在 BLACS_GRIDINIT 的描述中没有看到任何确保非参与进程的 ctxt 小于零的内容 - 在 https://www.netlib.org/blacs/BLACS/QRef.html#BLACS_GRIDINIT 它说
This routine creates a simple NPROW x NPCOL process grid. This process
grid will use the first NPROW x NPCOL processes, and assign them to
the grid in a row- or column-major natural ordering. If these
process-to-grid mappings are unacceptable, BLACS_GRIDINIT's more
complex sister routine BLACS_GRIDMAP must be called instead.
没有提到如果进程不是生成的网格的一部分,ctxt
会是什么 - 这是我经常在 BLACS 文档中发现的问题。也请不要使用 goto
,为您着想。你以后会后悔的。使用 If ... End If
。我不记得我上次在 Fortran 中使用 goto
是什么时候了,很可能是 10 多年前了。
终于祝您使用 BLACS 好运!根据我的经验,文档通常是不完整的,我建议只使用那些对于使用 ScaLAPACK 绝对必要的调用,并使用 MPI,它的定义要好得多,其余的。如果 ScaLAPACK 现在能和 MPI 一起工作,那就更好了。
我正在研究 ScaLAPACK 并尝试适应使用 ScaLAPACK 必不可少的 BLACS 例程。
我上过一些关于 MPI 的初级课程,所以对 MPI_COMM_WORLD 的东西有一些粗略的了解,但对它的内部工作原理等没有深入的了解。
无论如何,我正在尝试按照代码使用 BLACS 例程打招呼。
program hello_from_BLACS
use MPI
implicit none
integer :: info, nproc, nprow, npcol, &
myid, myrow, mycol, &
ctxt, ctxt_sys, ctxt_all
call BLACS_PINFO(myid, nproc)
! get the internal default context
call BLACS_GET(0, 0, ctxt_sys)
! set up a process grid for the process set
ctxt_all = ctxt_sys
call BLACS_GRIDINIT(ctxt_all, 'c', nproc, 1)
call BLACS_BARRIER(ctxt_all, 'A')
! set up a process grid of size 3*2
ctxt = ctxt_sys
call BLACS_GRIDINIT(ctxt, 'c', 3, 2)
if (myid .eq. 0) then
write(6,*) ' myid myrow mycol nprow npcol'
endif
(**) call BLACS_BARRIER(ctxt_sys, 'A')
! all processes not belonging to 'ctxt' jump to the end of the program
if (ctxt .lt. 0) goto 1000
! get the process coordinates in the grid
call BLACS_GRIDINFO(ctxt, nprow, npcol, myrow, mycol)
write(6,*) 'hello from process', myid, myrow, mycol, nprow, npcol
1000 continue
! return all BLACS contexts
call BLACS_EXIT(0)
stop
end program
'mpirun -np 10 ./exe' 的输出就像
hello from process 0 0 0 3 2
hello from process 4 1 1 3 2
hello from process 1 1 0 3 2
myid myrow mycol nprow npcol
hello from process 5 2 1 3 2
hello from process 2 2 0 3 2
hello from process 3 0 1 3 2
除了我在代码左侧标记 (**) 的 'BLACS_BARRIER' 行外,一切似乎都正常。
我已经放置了该行以生成如下所示的输出,其标题行始终打印在它的顶部。
myid myrow mycol nprow npcol
hello from process 0 0 0 3 2
hello from process 4 1 1 3 2
hello from process 1 1 0 3 2
hello from process 5 2 1 3 2
hello from process 2 2 0 3 2
hello from process 3 0 1 3 2
那么问题来了,
我试过BLACS_BARRIER到'ctxt_sys'、'ctxt_all'和'ctxt',但它们都没有输出标题行首先打印。我也试过 MPI_Barrier(MPI_COMM_WORLD,info),但也没用。我是不是用错了障碍?
另外,我在使用BLACS_BARRIER到'ctxt'时得到了SIGSEGV,并且在执行mpirun时使用了6个以上的进程。为什么在这种情况下会发生 SIGSEGV?
感谢您阅读这个问题。
回答你的2个问题(以后最好分开发帖)
1) MPI_Barrier、BLACS_Barrier 以及我遇到的任何并行编程方法中的任何障碍只会同步调用它的实际进程集。然而 I/O 并不仅仅由调用进程处理,而是至少在 OS 中处理 I/O 中的一个,并且很可能更多,它实际上处理 I/O 请求。这些不是由您的屏障同步的。因此 I/O 的排序不能通过简单的屏障来保证。我能想到的确保 I/O 排序的唯一符合标准的方法是
- 让 1 个进程完成所有 I/O 或
- 更好的方法是直接或间接使用 MPI I/O,例如通过NetCDF 或 HDF5
2) 您第二次致电 BLACS_GRIDINIT
call BLACS_GRIDINIT(ctxt, 'c', 3, 2)
为 3 x 2 进程网格创建上下文,因此包含 6 个进程。如果你用超过 6 个进程调用它,只有 6 个将被 return 编辑为有效的上下文,对于其他 ctxt
应该被视为未初始化的值。因此,例如,如果您使用 8 个进程调用它,则 6 个将 return 具有有效的 ctxt
,2 个将 return 具有 ctxt
没有有效值。如果这 2 个现在尝试使用 ctxt
任何事情都是可能的,在你的情况下你会遇到段错误。你似乎确实看到这是一个问题,因为后来你有
! all processes not belonging to 'ctxt' jump to the end of the program
if (ctxt .lt. 0) goto 1000
但我在 BLACS_GRIDINIT 的描述中没有看到任何确保非参与进程的 ctxt 小于零的内容 - 在 https://www.netlib.org/blacs/BLACS/QRef.html#BLACS_GRIDINIT 它说
This routine creates a simple NPROW x NPCOL process grid. This process grid will use the first NPROW x NPCOL processes, and assign them to the grid in a row- or column-major natural ordering. If these process-to-grid mappings are unacceptable, BLACS_GRIDINIT's more complex sister routine BLACS_GRIDMAP must be called instead.
没有提到如果进程不是生成的网格的一部分,ctxt
会是什么 - 这是我经常在 BLACS 文档中发现的问题。也请不要使用 goto
,为您着想。你以后会后悔的。使用 If ... End If
。我不记得我上次在 Fortran 中使用 goto
是什么时候了,很可能是 10 多年前了。
终于祝您使用 BLACS 好运!根据我的经验,文档通常是不完整的,我建议只使用那些对于使用 ScaLAPACK 绝对必要的调用,并使用 MPI,它的定义要好得多,其余的。如果 ScaLAPACK 现在能和 MPI 一起工作,那就更好了。