2014-11-06 1 views
1

Предполагая, что код упрощённого FORTRAN, скомпилированный с 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 из основных жду, пока ребенок не будет сделан с его расчетами , Тем не менее, я хочу, чтобы он продолжал выполнять свои задачи после вызова ребенка, в то время как ребенок также выполняет свои задачи. Я хотел бы, чтобы ребенок был подпрограммой для основного, поскольку мне нужно передать некоторые данные от основного к ребенку (но не наоборот). Мне было интересно узнать, возможно ли это в FORTRAN (возможно, используя какой-то неблокирующий вызов подпрограммы или многопоточность, например mpi_comm_spawn).

ответ

1

Для этого я бы использовал поток POSIX. Возможно, также задача OpenMP, но мой опыт с ними ограничен. Я предполагаю, что вы не вызываете никаких процедур MPI в child.

С помощью простого интерфейса в 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 для асинхронного вывода времени ступенчатых данных.