Fortran F90相当于void *与MPI或其他方式进行运行时类型检查?

时间:2015-03-09 17:52:31

标签: fortran mpi fortran90 void-pointers

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

我试图将MPI函数包装成一个通信层并封装直接的MPI交互(只是不能动摇那些OO的习惯!)。为此,我需要将数据传递给我的包装函数。

MPI spec有这个原型,例如:

INCLUDE ’mpif.h’
MPI_SEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
    <type>    BUF(*)
    INTEGER    COUNT, DATATYPE, DEST, TAG, COMM, IERROR

我的子程序是这样的:

SUBROUTINE empi_wrap_open_send(sendbuf, size, targetid, the_type)

我不得不添加'the_type'让我通过{*}传递正确的MPI dataype。但是,我无法将子程序的后续内部声明'sendbuf'编译。我试过了:

TYPE(C_PTR) :: sendbuf   !with 'USE iso_c_binding'
TYPE :: sendbuf(*)
POINTER :: sendbuf
POINTER, TYPE(*) :: sendbuf

我的最后一招是取消我的'IMPLICIT NONE',但我担心这样会导致灾难! 关于如何正确地做到这一点的任何提示,我将非常感激。肯定不是那么难吗?

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

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

但我可以忍受黑客攻击。

1 个答案:

答案 0 :(得分:3)

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

  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