Я пытаюсь понять, как DLL-библиотека Coarray Fortran может быть вызвана из Python.Рассмотрим следующий пример файла модуля Fortran example_mod.f90
, который будет вызван из Python позже:
module example_mod
use iso_c_binding
implicit none
#ifdef COARRAY_ENABLED
integer :: co_int[*]
#endif
interface
module subroutine sqr_2d_arr(nd, val, comm) BIND(C, NAME='sqr_2d_arr')
!DEC$ ATTRIBUTES DLLEXPORT :: sqr_2d_arr
integer, intent(in) :: nd
integer, intent(inout) :: val(nd, nd), comm
end subroutine sqr_2d_arr
end interface
contains
end module example_mod
с реализацией подпрограммы, указанной в файле подмодуля example_mod@sub_smod.f90
:
submodule (example_mod) sub_smod
implicit none
contains
module procedure sqr_2d_arr
use mpi
integer :: rank, size, ierr
integer :: i, j
call MPI_Comm_size(comm, size, ierr)
call MPI_Comm_rank(comm, rank, ierr)
write(*,"(*(g0,:,' '))") "Hello from Fortran MPI! I am process", rank, "of", size, ', comm:', comm
write(*,"(*(g0,:,' '))") "Hello from Fortran COARRAY! I am image ", this_image(), " out of", num_images(), "images."
sync all
do j = 1, nd
do i = 1, nd
val(i, j) = (val(i, j) + val(j, i)) ** 2
enddo
enddo
end procedure sqr_2d_arr
end submodule sub_smod
Подпрограмма также содержит обращения к библиотеке MPI для сравнения с Coarray.Я скомпилировал этот код со следующими флагами ifort:
mpiifort /Qcoarray=distributed /Od /debug:full /fpp -c example_mod.f90
mpiifort /Qcoarray=distributed /Od /debug:full /fpp -c example_mod@sub_smod.f90
mpiifort /Qcoarray=distributed /Od /debug:full /fpp /dll /libs:dll /threads example_mod.obj example_mod@sub_smod.obj
Теперь у меня есть следующий скрипт Python2, который вызывает сгенерированную DLL выше:
#!/usr/bin/env python
from __future__ import print_function
from mpi4py import MPI
comm = MPI.COMM_WORLD
fcomm = MPI.COMM_WORLD.py2f()
print("Hello from Python! I'm rank %d from %d running in total..." % (comm.rank, comm.size))
comm.Barrier() # wait for everybody to synchronize _here_
######################
import ctypes as ct
import numpy as np
# import the dll
fortlib = ct.CDLL('example_mod.dll')
# setup the data
N = 2
nd = ct.pointer( ct.c_int(N) ) # setup the pointer
pyarr = np.arange(0, N, dtype=int) * 5 # setup the N-long
for i in range(1, N): # concatenate columns until it is N x N
pyarr = np.c_[pyarr, np.arange(0, N, dtype=int) * 5]
# call the function by passing the ctypes pointer using the numpy function:
fcomm_pt = ct.pointer( ct.c_int(fcomm) )
_ = fortlib.sqr_2d_arr(nd, np.ctypeslib.as_ctypes(pyarr),fcomm_pt)
print(pyarr)
Запуск этого скрипта с помощью следующей команды:
mpiexec -np 4 python main.py
дает этот вывод:
Hello from Fortran MPI! I am process 1 of 4 , comm: 1140850688
Hello from Fortran MPI! I am process 3 of 4 , comm: 1140850688
Hello from Fortran COARRAY! I am image 1 out of 0 images.
Hello from Fortran MPI! I am process 0 of 4 , comm: 1140850688
Hello from Fortran COARRAY! I am image 1 out of 0 images.
Hello from Fortran MPI! I am process 2 of 4 , comm: 1140850688
Hello from Fortran COARRAY! I am image 1 out of 0 images.
Hello from Fortran COARRAY! I am image 1 out of 0 images.
Hello from Python! I'm rank 3 from 4 running in total...
[[ 0 25]
[900 100]]
Hello from Python! I'm rank 0 from 4 running in total...
[[ 0 25]
[900 100]]
Hello from Python! I'm rank 1 from 4 running in total...
[[ 0 25]
[900 100]]
Hello from Python! I'm rank 2 from 4 running in total...
[[ 0 25]
[900 100]]
Вычисления, выполненные в этом наборе кодов, не важны или не имеют отношения к обсуждению здесь.Однако я не могу понять, почему ранги MPI выводятся правильно, в то время как Coarray num_images () равен нулю для всех процессов.В целом, какова лучшая стратегия написания приложения Coarray Fortran, которое можно вызывать из других языков, таких как Python?