一旦声明,如何使用OpenMPI自定义数据类型?

时间:2014-08-20 06:00:05

标签: fortran mpi fortran90 openmpi custom-data-type

我想从我的主进程向MPI FORTRAN90实现中的所有其他进程广播非内存连续变量(INTEGERS和REAL(8))但是因为它是我第一次尝试FORTRAN和MPI(我只使用对于C / C ++),我几乎没有问题:

  • 目前我使用MPI_TYPE_CREATE_STRUCT调用,但我知道我也可以使用MPI_PACK / MPI_UNPACK调用,这些调用需要额外的内存到内存复制操作。由于在这种情况下要播放的数据不是那么大,什么解决方案提供最佳性能?还有其他我不知道的解决方案,哪些解决方案更快/更简单(每个变量可能有一个MPI_BCAST调用?)?

  • 对于自定义MPI数据类型,如何将变量(或此处的一组已知数据类型变量)声明为新数据类型的一个变量?我的意思是现在创建了我的MPI结构PARAMETER_READ(参见下面的代码),如何告诉编译器我想要存储在内存中的所有变量(nmin,dout,nmax,ncellsmax,ncells,ns,dt,del)将所有组合在一起只成为PARAMETER_READ类型的一个新变量?

  • 我在哪里声明自定义数据类型?我应该在a:

    中声明它们

    IF(rank == 0)那么

    声明新数据类型

    ENDIF

循环还是外部?

这是我的代码(我只保留了有趣的部分):

PROGRAM SIM_3D
USE IO
USE MPI_MOD

IMPLICIT NONE

INTEGER :: nmin, dout, nmax, ncellsmax
INTEGER, DIMENSION(3) :: ncells, ns
REAL(8) :: dt,
REAL(8), DIMENSION(3) :: del

CALL init_MPI

IF(rank == master) THEN
  CALL readParams(ncells, del, nmin, dout, nmax, dt, ns, ncellsmax) ! All these values are read by the master process in an external *.txt file using a custom subroutine readParams in the IO module.
  CALL BCAST_PARAM
ENDIF

END PROGRAM SIM_3D

MPI_MOD在哪里:

MODULE MPI_MOD

USE MPI

INTEGER, PARAMETER :: master = 0
INTEGER :: ierror, rank, num_proc
INTEGER, DIMENSION( MPI_STATUS_SIZE ) :: status

INTEGER :: NUMBER_OF_BLOCKS = 2
INTEGER, DIMENSION(2) :: ARRAY_OF_BLOCKLENGTHS = (/ 10, 4/)
INTEGER, DIMENSION(2) :: ARRAY_OF_DISPLACEMENTS = (/ 40, 32/)
INTEGER, DIMENSION(2) :: ARRAY_OF_TYPES = (/ MPI_INTEGER, MPI_REAL/)

CONTAINS

SUBROUTINE init_MPI
  IMPLICIT NONE
  CALL MPI_INIT(ierror)
  CALL MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierror)
  CALL MPI_COMM_SIZE(MPI_COMM_WORLD,num_proc,ierror)
END SUBROUTINE init_MPI

SUBROUTINE BCAST_PARAM
  IMPLICIT NONE
  CALL MPI_TYPE_CREATE_STRUCT(NUMBER_OF_BLOCKS, ARRAY_OF_BLOCKLENGTHS, ARRAY_OF_DISPLACEMENTS, ARRAY_OF_TYPES, PARAMETER_READ, IERROR)
  CALL MPI_TYPE_COMMIT (PARAMETER_READ, IERROR)
  *I would like to put all the variables to be sent in a PARAMETER_READ type variable called BUFFER*
  CALL MPI_BCAST(BUFFER,1,PARAMETER_READ,master,MPI_COMM_WORLD,IERROR)
END SUBROUTINE BCAST_PARAM

END MODULE MPI_MOD

我甚至不确定我的自定义数据类型声明是否正确... 非常感谢您阅读我,非常感谢您的帮助。 最好的问候。

1 个答案:

答案 0 :(得分:1)

回答您的上一个问题:自定义MPI数据类型需要由所有进程声明,而不仅仅是主节点。这也适用于集体通信,例如MPI_BCAST,因此您应该将呼叫转移到BCAST_PARAM阻止之外的if(rank == master)

对于您的第一个问题,您最好的选择是进行一些实证检验。很难说实际用例的速度会更快,因为它还取决于您传达数据的次数以及您运行的机器的详细信息。

MPI数据类型仅在MPI例程中用于传递数据。如果要将多个Fortran变量打包在一起,最简单的方法是创建一个与MPI数据类型匹配的Fortran派生类型。以下是您的案例的样子:

! For kind=REAL64, more portable than kind=8
use, intrinsic :: iso_fortran_env

type parameter_read_type
   integer                    :: nmin
   integer                    :: dout
   integer                    :: nmax
   integer                    :: ncellsmax
   integer, dimension(3)      :: ncells
   integer, dimension(3)      :: ns
   real(REAL64)               :: dt
   real(REAL64), dimension(3) :: del
end type parameter_read_type

然后,您可以将新变量声明为此类型,并使用%运算符访问组件:

type(parameter_read_type) :: buffer

if (rank == master) call readParams(buffer)

call MPI_BCAST(buffer, 1, PARAMETER_READ, master, MPI_COMM_WORLD, ierror)

...

subroutine readParams(read_parameters)
  type(parameter_read_type), intent(out) :: read_parameters

  read_parameters%nmin = ...
  read_parameters%ncells(1) = ...

  ...

end subroutine readParams

创建这样的Fortran类型也可以让你传递parameter_read_type

的数组
type(parameter_read_type), dimension(2) :: buffer2

call readParams(buffer2(1))
call readParams(buffer2(2))

call MPI_BCAST(buffer2, 2, PARAMETER_READ, master, MPI_COMM_WORLD, ierror)