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

Fortran 一旦声明,如何使用OpenMPI自定义数据类型?,fortran,mpi,fortran90,openmpi,custom-data-type,Fortran,Mpi,Fortran90,Openmpi,Custom Data Type,在MPI FORTRAN90实现中,我想将非内存连续变量(整数和实数(8))从主进程广播到所有其他进程,但由于这是我第一次尝试FORTRAN和MPI(我只使用C/C++),我有几个问题: 目前我使用MPI_TYPE_CREATE_STRUCT调用,但我知道我也可以使用MPI_PACK/MPI_UNPACK调用,这需要额外的内存到内存复制操作。既然在这种情况下要广播的数据不是那么大,那么哪种解决方案能够提供最好的性能?是否有其他我不知道的解决方案,并且实现起来更快/更简单(每个变量可能有一个MP

在MPI FORTRAN90实现中,我想将非内存连续变量(整数和实数(8))从主进程广播到所有其他进程,但由于这是我第一次尝试FORTRAN和MPI(我只使用C/C++),我有几个问题:

  • 目前我使用MPI_TYPE_CREATE_STRUCT调用,但我知道我也可以使用MPI_PACK/MPI_UNPACK调用,这需要额外的内存到内存复制操作。既然在这种情况下要广播的数据不是那么大,那么哪种解决方案能够提供最好的性能?是否有其他我不知道的解决方案,并且实现起来更快/更简单(每个变量可能有一个MPI_BCAST调用?)

  • 在自定义MPI数据类型的情况下,如何将一个变量(或者这里是一组已知的数据类型变量)声明为新数据类型的一个变量?我的意思是,现在我的MPI结构参数_READ已经创建(请参见下面的代码),我如何告诉编译器我希望所有存储在内存中的变量(nmin、dout、nmax、ncellsmax、ncells、ns、dt、del)都分组在一起,成为PARAMETER_READ类型的一个新变量

  • 在哪里声明自定义数据类型?我是否应该在一份声明中声明:

    如果(秩==0),则

    新数据类型的声明

    恩迪夫

环路还是外部

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

其中,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
我甚至不确定我的自定义数据类型声明是否正确。。。 非常感谢您阅读我的文章,非常感谢您的帮助。
致意。

回答您的最后一个问题:定制MPI数据类型需要由所有进程声明,而不仅仅是主节点。这也适用于集体通信,如
MPI\u BCAST
,因此您应该将调用移动到
BCAST\u 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类型还可以让您传递
参数\u read\u类型的数组

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)

你能澄清你的第二点是什么意思吗?你会在你的代码中多次交流这些变量吗?嗨,Yossarian,谢谢你的快速回答。我试图用我的第二个要点尽可能清楚地表达我的观点,我希望这足以让你们理解我的问题。谢谢你的帮助!您所追求的是Fortran派生类型。我已经在我的回答中添加了这一点。谢谢你的回答,也谢谢你花时间在这个话题上。恐怕我还不够清楚。实际上,我确实希望使用MPI例程将前面提到的所有变量传递给集群的所有节点,但我只想使用一个
MPI\u BCAST
调用,这就是为什么我想“打包”-或类似的东西-只有一个变量中的数据可以在
MPI\u BCAST
中使用。在这种情况下,为什么不建议使用带有
MPI\u TYPE\u CREATE\u STRUCT
的MPI自定义数据类型?我还有另一个类似的问题:因为我在代码中使用笛卡尔拓扑,所以我想使用
MPI\u CREATE\u DARRAY
与每个节点通信一个3D数组,该数组是从更大的源3D数组的一部分创建的,其中包含它必须处理的数据。创建MPI自定义数据类型后,如何使用它并声明所有子数组?事实上,我不知道在创建MPI自定义数据类型后如何使用它们,以及如何影响新类型变量的值。
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)