python+fortranでmpi並列

python + fortran

pythonからfortranのサブルーチン等を用いるには,pythonのctypesを用いる.

fortranでISO_C_bindingを用いる必要はなさげ.

 

pythonでのmpi

mpi4pyを用いる.

pythonかつfortranでmpi

py2f()でcommをfortran仕様に変換してやることで,fortranのコード内でも並列計算のつぎ込み方等を決めることができる.fortranではuse mpiを指示する.

 

fortranでmpi+openmp

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と連携できない.

 

追記:

intelpython向け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でコンパイルし直すと、計算できるようになった。どうもintelpythonをインストールして、放置していたためらしい。上記で何をやっていたか、記憶をたどる。

どうも、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に乗り換えるか!