在FORTRAN中调用子例程而不阻塞主程序

时间:2014-11-06 23:46:00

标签: multithreading fortran blocking

假设使用mpif90编译的过度简化的FORTRAN代码为:

program main
!
   use mpi
   implicit none
   integer:: j, numtasks, taskid, ierr
   integer:: master = 0
!
   call mpi_init(ierr)
   call mpi_comm_rank(mpi_comm_world, taskid, ierr)   
!
   if (taskid .eq. master) then
      j = 5
      call child (j)
  !   do stuff
   end if
   call mpi_finalize(ierr)
!
end program main

subroutine child(j)
!
   implicit none
   integer, intent(in):: j
!  do some stuff with j
end subroutine child

默认情况下,main中的主CPU等待子进程完成计算。但是,我希望它在调用孩子后继续执行任务,而孩子也在完成任务。我希望孩子成为主要的子程序,因为我需要将一些数据从主要传递给孩子(但反之亦然)。我想知道在FORTRAN中是否可以这样做(可能通过使用某种非阻塞子程序调用或多线程如mpi_comm_spawn)。

1 个答案:

答案 0 :(得分:1)

我会使用POSIX线程。也许也是一个OpenMP任务,但我对它们的体验是有限的。我假设你没有在child中调用任何MPI程序。

在C

中使用简单的界面
#include <pthread.h>

void pthread_create_opaque(pthread_t *threadptr, void *procptr, void *dataptr, int *err){
//   creates a new thread using an opaque pointer to the pthread_t structure
  *err = pthread_create(threadptr, NULL, procptr, dataptr);
}

void pthread_join_opaque(pthread_t *threadptr, int *err) {
//  joines a thread using an opaque pointer to the pthread_t structure
 *err = pthread_join(*threadptr, NULL);
}

和Fortran

module Pthreads
  implicit none

  interface
    subroutine pthread_create_opaque(threadptr, procptr, dataptr, err) bind(C,name="pthread_create_opaque")
      use iso_c_binding
      type(c_ptr) :: threadptr
      type(c_funptr),value :: procptr
      type(c_ptr),value :: dataptr
      integer(c_int),intent(out) :: err
    end subroutine

    subroutine pthread_join_opaque(thread, err) bind(C,name="pthread_join_opaque")
      use iso_c_binding
      type(c_ptr),value :: thread
      integer(c_int),intent(out) :: err
    end subroutine
  end interface
end module Pthreads

如果孩子是C可互操作的话,你可以给孩子打电话

subroutine child(j) bind(C)
!
   implicit none
   integer, intent(in):: j
!  do some stuff with j
end subroutine child

简单地说就是

type(c_ptr) :: thread
integer :: err

call pthread_create_opaque(thread, c_funloc(join), loc(j), err)

以及稍后在某个方便的地方(在节目结束之前或在任何地方)等待它完成其工作

call pthread_join_opaque(thread, err)

我在MPI并行程序中成功使用它来异步输出时间步数据。