【问题标题】:Calling a subroutine in FORTRAN without blocking the main program在 FORTRAN 中调用子程序而不阻塞主程序
【发布时间】:2014-11-08 20:05:59
【问题描述】:

假设使用 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

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

【问题讨论】:

    标签: multithreading fortran blocking


    【解决方案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 并行程序中成功地使用了它来异步输出时间步长数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-27
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      • 1970-01-01
      • 2021-10-19
      相关资源
      最近更新 更多