我试图了解如何从Python调用Coarray Fortran DLL。考虑以下示例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()对于所有进程都是零。作为一个更广泛的问题,编写可从其他语言(如Python)调用的Coarray Fortran应用程序的最佳策略是什么?