【问题标题】:Fortran F90 equivalent of void* with MPI or another way to do runtime type checking?使用 MPI 或其他方式进行运行时类型检查的 Fortran F90 等效于 void*?
【发布时间】:2015-05-10 23:59:04
【问题描述】:

我已经花了几天时间搜索了很多东西(包括这个网站和 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 数据类型。但是,我无法编译子例程随后的“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

但我可以接受黑客攻击。

【问题讨论】:

  • 您提到了 Fortran 90,但您使用的是(至少)Fortran 2003。您能否澄清一下哪个编译器(mpif90 会环绕某些东西,如果这就是您的意思)为有些人有支持,这会让事情变得更容易?
  • 删除 implicit none 不会使这项工作:允许隐式输入,而您想要一些非常不同的东西。
  • 是的,我无法删除“隐式无”。我不是故意使用 F2003,我使用的是 mpif90。我正在尝试包装 MPI 例程,仅此而已,没有编译器并发症!
  • select type 不起作用,因此我的破解!而且我认为iso_c_binding 也失败了,因此我对TYPE(C_PTR) 选项也有问题。我基本上是在尝试做不可能的事情吗?
  • 取决于你想要做什么,然后泛型可能是一种方法。恐怕我现在没有时间多说。

标签: fortran mpi fortran90 void-pointers


【解决方案1】:

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

  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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    • 1970-01-01
    • 2018-12-22
    相关资源
    最近更新 更多