pythonからfortranのサブルーチン等を用いるには,pythonのctypesを用いる.
fortranでISO_C_bindingを用いる必要はなさげ.
○pythonでのmpi
mpi4pyを用いる.
py2f()でcommをfortran仕様に変換してやることで,fortranのコード内でも並列計算のつぎ込み方等を決めることができる.fortranではuse mpiを指示する.
fortran内では,openmpとmpiのハイブリッドも可能.
mpiで大枠の並列をつくり,そのなかでopenmpを行うイメージ.
○注意点
condaでmpi4pyをインストールするとmpichもくっついてきた.
このくっついてきたmpichのmpif90やmpirunを用いることで,fortranの並列コードのコンパイルや,python+fortranの並列計算のmpirunが実行できる.ただし,デフォルトのmpifortのFCの指定をgfortranに正す必要があった.
mpirun -np 2 paralell_script.py
condaで導入されるのはコンパイル済みのパッケージなので,他のやり方でインストールしたmpif90を用いてしまうと,mpi4pyを介してpythonと連携できない.
追記:
intelはpython向けintel distributionを出しており(Intel distribution for python),これを用いると,mpiifortでのfortran+pythonの並列計算ができる.このパッケージに入っていないライブラリはcondaでインストールできる.
Intel parallel studioにはこのpython向けパッケージも含まれており,/opt/intel以下にルート権限でインストールされる.しかしこの場合はconda環境が構築されておらず,ライブラリの
追加が困難.自分のhome以下にIntel distribution for pythonを個別にインストールすることで回避できる.
残念ながら,自分のプログラムでは,mpiifortよりgfortranのmpif90のほうが速いし,メモリも食わないという現状.
追記2:
しばらく放置していたら、mpirunで並列計算ができなくなっている!
mpichはインストールされていない。openmpiとmpi4pyをインストールしなおし、conda配下のmpif90でコンパイルし直すと、計算できるようになった。どうもintelのpythonをインストールして、放置していたためらしい。上記で何をやっていたか、記憶をたどる。
どうも、historyでみると、
https://www.isus.jp/products/python-distribution/using-intel-distribution-for-python-with-anaconda/
を参考にして、intelのconda環境をidpという名前で作り、うまくいかないので環境を削除したようだ。
conda info --envs
で確認すると、 $HOMEの下にtargzfiles/intelpython3
とある。
これは、intelのサイトからダウンロードしたl_pythoni3_p_2020.1.893.tar.gzを展開し、mpiifortでコンパイルしたプログラムが走るところまでもっていったもののようだである。
しかし、source activateでこの環境に入ってしまうと、なぜかmpiifortでコンパイルしようとすると、mpiがインクルードできない。環境に入らずに、mpiifortでまずコンパイルし、その後、この環境に入り、mpirunを実行すると、並列計算できることを確認した。(しかし計算速度は遅い)
intelpythonと普段遣いのconda環境に入れることも試みたようで、現在、
intelpythonとimpi_rtというパッケージを普段遣いのconda環境に入ってしまっている状況。intelのchannelが優先されている状況。
conda config --show channels
まず、このチャンネル自体を削除。
conda config --remove channels intel
さらに、intelpython, impi_rtも削除。
conda remove intelpython impi_rt
intelpython impi_rt削除時に、色々パッケージの更新がなされ、openmpiがなくなったようなので、openmpiとmpi4pyを改めてインストール。
conda install openmpi mpi4py
これで、gfortranのopenmpiでコンパイルしたプログラムが走るようになった。
intelの並列計算が早ければ、intelpythonを扱う努力をしてもよいが、$HOME/targzfiles/intelpython3で動くことを確認しただけにとどめていおく。
追記:2022/04/09
miniconda配下のopenmpiを用いて適当なmpiを用いたメインプログラムのファイルをコンパイルしようとすると、
mpif90 test.f90
.soファイルがundefineded エラー。
condaでインストールされるopenmpiの想定しているlibやgfortranのバージョンがあっていないためであった。 7.5.0のバージョンに揃えれば問題なくコンパイルできた。
追記:2022/04/09
なんでmpif90でコンパイルしようとしたかというと、2次元の配列に1次元ベクトルの情報をぶち込みたかったからである。
今まで、1次元の配列に1次元のベクトルの情報をぶち込み(allgather)、reshapeして2次元にしていた。これだと、メモリが増えると思われるので、2次元のままぶち込みたい。fortranの場合、
1番めの引数に優先的に配列が仕込まれていく。
program testmpi
include 'mpif.h'
double precision, dimension(8, 2) :: A
double precision :: b(8)
integer :: rank, psize, ierr
call MPI_Init(ierr)
call MPI_Comm_size(MPI_COMM_WORLD, psize, ierr)
call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
A = 0.
do i = 1, 8
b(i) = i + rank*32
enddo
call mpi_allgather(b, 8, mpi_double_precision, A, 8, mpi_double_precision, mpi_comm_world, ierr)
if (rank == 0) then
print *, A(:,1)
print *, A(:,2)
endif
call MPI_Finalize(ierr)
stop
end
mpirun -np 2 a.out
1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 6.0000000000000000 7.0000000000000000 8.0000000000000000
33.000000000000000 34.000000000000000 35.000000000000000 36.000000000000000 37.000000000000000 38.000000000000000 39.000000000000000 40.000000000000000
Aを(4,4)とすると、 print *, A(:,3), A(:,4)も入れると、
1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000
5.0000000000000000 6.0000000000000000 7.0000000000000000 8.0000000000000000
33.000000000000000 34.000000000000000 35.000000000000000 36.000000000000000
37.000000000000000 38.000000000000000 39.000000000000000 40.000000000000000
となり、まず、一番目の引数のシーケンスを満たし、はみ出した部分は2番めの引数を1つ上げ、
1番目のシーケンスを更に満たしていく。pythonやCだと順番が逆であると思われる。
2022/05/17 mpiまわりで不具合
conda環境で,pybind11というパッケージを入れたら,pythonでmpi並列 mpif90でコンパイルしたライブラリが不具合.print *, "CHK"をライブラリのソースに入れてやると問題なく走る. intelのoneapiでは何も問題なく走る.linux(ubuntu18)だけでなく,macでも同じ.
intelのoneapiでの実行速度が速ければそちらを使うことも考えられるが,遅い.多数回繰り返しライブラリを使うのでprint文は除きたい.mac上での新たなconda環境のpythonは3.8.13.かなり新しい.python=3.6をインストールすると,問題は解消した.
mac 上でのconda環境
conda create -n mpi
source miniconda3/etc/profile.d/conda.sh
conda activate mpi
conda install mpi4py
conda install numpy
conda install matplotlib
conda install gfortran_osx-64
conda install python=3.6
で走るようになった.
conda list
# packages in environment at /Users/kazu/opt/miniconda3/envs/mpi:
#
# Name Version Build Channel
blas 1.0 mkl
brotli 1.0.9 hb1e8313_2
ca-certificates 2022.4.26 hecd8cb5_0
certifi 2021.5.30 py36hecd8cb5_0
cycler 0.11.0 pyhd3eb1b0_0
fonttools 4.25.0 pyhd3eb1b0_0
freetype 2.11.0 hd8bbffd_0
gfortran_osx-64 4.8.5 h22b1bf0_8
giflib 5.2.1 haf1e3a3_0
intel-openmp 2021.4.0 hecd8cb5_3538
jpeg 9e hca72f7f_0
kiwisolver 1.3.1 py36h23ab428_0
lcms2 2.12 hf1fd2bf_0
libcxx 12.0.0 h2f01273_0
libffi 3.3 hb1e8313_2
libgfortran 3.0.1 h93005f0_2
libpng 1.6.37 ha441bb4_0
libtiff 4.2.0 h87d7836_0
libwebp 1.2.2 h56c3ce4_0
libwebp-base 1.2.2 hca72f7f_0
lz4-c 1.9.3 h23ab428_1
matplotlib 3.1.1 py36h54f8f79_0
mkl 2021.4.0 hecd8cb5_637
mpi 1.0 mpich
mpi4py 3.0.3 py36h77202c6_0
mpich 3.3.2 hc856adb_0
munkres 1.1.4 py_0
ncurses 6.3 hca72f7f_2
numpy 1.14.2 py36ha9ae307_0
openssl 1.1.1o hca72f7f_0
packaging 21.3 pyhd3eb1b0_0
pip 21.2.2 py36hecd8cb5_0
pyparsing 3.0.4 pyhd3eb1b0_0
python 3.6.13 h88f2d9e_0
python-dateutil 2.8.2 pyhd3eb1b0_0
pytz 2021.3 pyhd3eb1b0_0
readline 8.1.2 hca72f7f_1
setuptools 58.0.4 py36hecd8cb5_0
six 1.16.0 pyhd3eb1b0_1
sqlite 3.38.3 h707629a_0
tk 8.6.11 h3fd3227_1
tornado 6.1 py36h9ed2024_0
wheel 0.37.1 pyhd3eb1b0_0
xz 5.2.5 hca72f7f_1
zlib 1.2.12 h4dc903c_2
zstd 1.4.9 h322a384_0
linux(ubuntu18)でもpythonのバージョンを下げてみたい.
2022/05/17 追記:
linux(ubuntu18)でもトライしてみた。が、失敗。condaのセットアップからやり直したが, プロセス数が2程度なら走るも32ではエラー。macでは2しか試していなかった。conda環境での対処策としてwrite(10,*) rankを初めに入れると問題なく計算できる。fort.10が余分に生成されるが問題ではない。
さらに、oenapiでもう一度試してみたところfftw3まわりでエラーがでる。mklのfftw3はソースファイルそのままで単にインクルードファイルをintel mklのものを指定すればよい。
source /opt/intel/oneapi/setvars.sh
mpif90 -O3 -shared -fPIC -o ssvkernel_f90_mpi.so ssvkernel_mpi.f90 -I/opt/intel/oneapi/mkl/2022.0.2/include/fftw
これで計算速度を実測。
mpirun -np 32 qens_qselected_using_class_fort_mpi.py 6203 0000025io 160 1 186.90s user 18.60s system 2987% cpu 6.878 total
いっぽう、condaでの計算速度。
mpirun -np 32 qens_qselected_using_class_fort_mpi.py 6203 0000025io 160 1 216.11s user 17.63s system 1695% cpu 13.784 total
intel oneapiのほうが速い。print/write文挟む手間もないし、ライブラリのインストールの手間もないし、長らく使えるようならintel oneapiに乗り換えるか!