在FORTRAN中调用子程序而不阻塞主程序 [英] Calling a subroutine in FORTRAN without blocking the main program

查看:283
本文介绍了在FORTRAN中调用子程序而不阻塞主程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 程序main 

使用mpi
隐式无
整数:: j,numtasks,taskid,ierr
integer :: master = 0

调用mpi_init(ierr)
调用mpi_comm_rank(mpi_comm_world,taskid,ierr)

if(taskid .eq。master)then
j = 5
call child(j)
!做的东西
结束如果
调用mpi_finalize(ierr)

结束程序主
$ b $子程序子(j)

隐式无
整数,意图(in):: j
!使用j
做一些事情结束子例程子

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

解决方案

我会为此使用POSIX线程。也许也是一个OpenMP任务,但我的经验是有限的。我假定你不会在中调用任何MPI过程。



通过C



  #include< pthread.h> 

void pthread_create_opaque(pthread_t * threadptr,void * procptr,void * dataptr,int * err){
//使用指向pthread_t结构的不透明指针创建新线程
* err = pthread_create(threadptr,NULL,procptr,dataptr);
}

void pthread_join_opaque(pthread_t * threadptr,int * err){
//使用opaque指针指向pthread_t结构
* err = pthread_join (* threadptr,NULL);
}

和Fortran
< pre pre $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' pthread_create_opaque)
使用iso_c_binding
类型(c_ptr):: threadptr
类型(c_funptr),value :: procptr
类型(c_ptr),value :: dataptr
整数(c_int),intent(out):: err
结束子程序

子程序pthread_join_opaque(thread,err)bind(C,name =pthread_join_opaque)
use iso_c_binding
$(b_btr),value :: thread
integer(c_int),intent(out):: err
结束子程序
结束接口
结束模块Pthreads

你可以调用一个孩子,如果它是C可互操作的

 子例程子(j)绑定(C)

隐式无
整数,意图(in):: j
!做一些与j
结尾子程序子

的东西简单地作为

  type(c_ptr):: thread 
integer :: err

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

然后在某个方便的地方(在程序结束或任何地方)等待为它完成工作

  call pthread_join_opaque(thread,err)

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


Assuming an over-simplified FORTRAN code compiled with mpif90 as:

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

By default, the master CPU from the main waits until the child is done with its calculations. However, I want it to continue its tasks after calling the child, while the child is also doing its tasks. I would like the child to be a subroutine for the main since I need to pass some data from the main to the child (but not vice versa). I was wondering to know if this is possible in FORTRAN (maybe by using some kind of non-blocking subroutine call or multi-threading such as mpi_comm_spawn).

解决方案

I would use a POSIX thread for this. Maybe also an OpenMP task, but my experience with them is limited. I will assume you do not call any MPI procedures in the child.

With a simple interface in 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);
}

and in 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

you can call a child if it is C interoperable

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

simply as

type(c_ptr) :: thread
integer :: err

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

and later at some convenient place (before program end or wherever) wait for it to finish its work

call pthread_join_opaque(thread, err)

I use this successfully in an MPI parallel program for asynchronous output of time-step data.

这篇关于在FORTRAN中调用子程序而不阻塞主程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆