Fortran F90相当于void*,使用MPI还是其他执行运行时类型检查的方法?

Fortran F90相当于void*,使用MPI还是其他执行运行时类型检查的方法?,fortran,mpi,fortran90,void-pointers,Fortran,Mpi,Fortran90,Void Pointers,我已经花了好几天的时间研究这个问题,搜索了很多东西(包括这个网站和Fortran文档),所以如果这是一个非常简单的问题,请原谅,但我对Fortran相对缺乏经验,并且来自C++/C#/Java背景。 我使用的是F90 MPI编译器,因此无法使用任何最新的功能,对此我没有选择 我正在尝试包装MPI函数,以封装通信层和直接MPI交互(只是无法改变这些OO习惯!)。为此,我需要向包装器函数传递数据或从包装器函数传递数据 该模型具有以下原型,例如: INCLUDE ’mpif.h’ MPI_SEND(B

我已经花了好几天的时间研究这个问题,搜索了很多东西(包括这个网站和Fortran文档),所以如果这是一个非常简单的问题,请原谅,但我对Fortran相对缺乏经验,并且来自C++/C#/Java背景。 我使用的是F90 MPI编译器,因此无法使用任何最新的功能,对此我没有选择

我正在尝试包装MPI函数,以封装通信层和直接MPI交互(只是无法改变这些OO习惯!)。为此,我需要向包装器函数传递数据或从包装器函数传递数据

该模型具有以下原型,例如:

INCLUDE ’mpif.h’
MPI_SEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
    <type>    BUF(*)
    INTEGER    COUNT, DATATYPE, DEST, TAG, COMM, IERROR
我必须添加'the_type',以便通过{*}传递正确的MPI数据类型。但是,我无法编译子例程随后的内部声明'sendbuf'。我试过:

TYPE(C_PTR) :: sendbuf   !with 'USE iso_c_binding'
TYPE :: sendbuf(*)
POINTER :: sendbuf
POINTER, TYPE(*) :: sendbuf
我最后的办法是删除我的“隐式无”,但我担心那样会导致灾难! 如果有任何关于如何正确操作的建议,我将不胜感激。肯定不会那么难吧

{*}我宁愿做运行时类型检查,即:

SELECT TYPE (sendbuf)
TYPE is (INTEGER)
    empi_type = MPI_INTEGER
TYPE is (DOUBLE)
    empi_type = MPI_DOUBLE_PRECISION
END SELECT

但我可以忍受黑客

我会使用泛型。当然,它会带来一些代码重复,但是您会得到类型检查和其他良好的特性。下面是我在生产中实际使用的代码片段。我发现以这种方式包装Send和Recv没有什么用处(我使用不同的内部过程作为包装器),但我确实包装了MPI collectives。最后一个函数显示您根本不需要传递大小

  interface mpi_co_min
    module procedure mpi_co_min_32
    module procedure mpi_co_min_64
  end interface

  ...

  interface mpi_co_reduce
    module procedure mpi_co_reduce_32
    module procedure mpi_co_reduce_64
    module procedure mpi_co_reduce_32_1d
    ...
  end interface

  ...

  function mpi_co_min_32(x) result(res)
    real(real32) :: res
    real(real32),intent(in) :: x
    integer ie

    res = mpi_co_reduce(x, MPI_MIN, global_comm)
  end function

  function mpi_co_min_64(x) result(res)
    real(real64) :: res
    real(real64),intent(in) :: x
    integer ie

    res = mpi_co_reduce(x, MPI_MIN, global_comm)
  end function

  function mpi_co_reduce_32(x,op,comm) result(res)
    real(real32) :: res
    real(real32),intent(in) :: x
    integer, intent(in) :: op, comm
    integer ie

    call MPI_AllReduce(x, res, &
                       count=1, datatype=MPI_MI_REAL32, op=op, &
                       comm=comm, ierror=ie)
  end function

  function mpi_co_reduce_64(x,op,comm) result(res)
    real(real64) :: res
    real(real64),intent(in) :: x
    integer, intent(in) :: op, comm
    integer ie

    call MPI_AllReduce(x, res, &
                       count=1, datatype=MY_MPI_REAL64, op=op, &
                       comm=comm, ierror=ie)
  end function

  function mpi_co_reduce_32_1d(x,op,comm) result(res)
    real(real32),intent(in) :: x(:)
    real(real32) :: res(size(x))
    integer, intent(in) :: op, comm
    integer ie

    call MPI_AllReduce(x, res, &
                       count=size(x), datatype=MY_MPI_REAL32, op=op, &
                       comm=comm, ierror=ie)
  end function

你提到了Fortran 90,但你使用的(至少)是Fortran 2003。你能澄清一下哪个编译器(
mpif90
将围绕某个东西进行编译,如果这是你的意思的话)因为有些编译器支持使事情变得更简单吗?删除
implicit none
不会使这项工作起作用:它允许隐式键入,而你想要的是非常不同的东西。是的,我不想删除“implicit none”。我不是故意使用F2003,而是使用mpif90。我正在尝试包装MPI例程,仅此而已,没有编译器并发症<代码>选择类型不起作用,因此我的黑客!我认为
iso_c_绑定
也失败了,因此我的
类型(c_PTR)
选项也有问题。我基本上是在尝试做不可能的事情吗?取决于你想做什么,那么泛型可能是一种方法。恐怕我现在没时间多说了。
  interface mpi_co_min
    module procedure mpi_co_min_32
    module procedure mpi_co_min_64
  end interface

  ...

  interface mpi_co_reduce
    module procedure mpi_co_reduce_32
    module procedure mpi_co_reduce_64
    module procedure mpi_co_reduce_32_1d
    ...
  end interface

  ...

  function mpi_co_min_32(x) result(res)
    real(real32) :: res
    real(real32),intent(in) :: x
    integer ie

    res = mpi_co_reduce(x, MPI_MIN, global_comm)
  end function

  function mpi_co_min_64(x) result(res)
    real(real64) :: res
    real(real64),intent(in) :: x
    integer ie

    res = mpi_co_reduce(x, MPI_MIN, global_comm)
  end function

  function mpi_co_reduce_32(x,op,comm) result(res)
    real(real32) :: res
    real(real32),intent(in) :: x
    integer, intent(in) :: op, comm
    integer ie

    call MPI_AllReduce(x, res, &
                       count=1, datatype=MPI_MI_REAL32, op=op, &
                       comm=comm, ierror=ie)
  end function

  function mpi_co_reduce_64(x,op,comm) result(res)
    real(real64) :: res
    real(real64),intent(in) :: x
    integer, intent(in) :: op, comm
    integer ie

    call MPI_AllReduce(x, res, &
                       count=1, datatype=MY_MPI_REAL64, op=op, &
                       comm=comm, ierror=ie)
  end function

  function mpi_co_reduce_32_1d(x,op,comm) result(res)
    real(real32),intent(in) :: x(:)
    real(real32) :: res(size(x))
    integer, intent(in) :: op, comm
    integer ie

    call MPI_AllReduce(x, res, &
                       count=size(x), datatype=MY_MPI_REAL32, op=op, &
                       comm=comm, ierror=ie)
  end function