petsc4py のインストール

2016年9月1日

はじめに

petsc4py のインストールについて。

環境

  • PETSc 3.7.3/petsc4py 3.7.0
  • Windows 7 64 bit
  • Cygwin/MinGW w64
  • Anaconda3 4.1.1
  • Microsoft Windows SDK v7.1

Linux の場合

Linux の場合は pip で問題なくインストールできるはず。

$ pip install mpi4py
$ pip install petsc
$ pip install petsc4py

Windows の場合

環境整備

以下のものをインストールする。

Windows SDK と Microsoft MPI はコンパイルに必要。Cygwin はなぜか PETSc が Cygwin の Python 2.x を必要とするためである。

もともと MinGW (MSYS2) が入っていたので、影響している可能性もあり (関係ないとは思うが…)。

PETSc

petsc4py が前提としている PETSc ライブラリをコンパイルする。

こちら から "petsc-lite-3.7.3.tar.gz" をダウンロードし、展開する。

Cygwin ターミナルを起動。Windows SDK の link を使うためにリネームしておく。

$ mv /usr/bin/link.exe /usr/bin/link-cygwin.exe

以下のように実行。

$ export PATH=/usr/bin:$PATH
$ cd petsc-3.7.3/
$ export PATH=$PATH:`pwd`/bin/win32fe
$ ./configure --with-cc="win32fe cl" --with-fc=0 --download-f2cblaslapack --with-mpi-include="/cygdrive/c/Program Files (x86)/Microsoft SDKs/MPI/Include" --with-mpi-lib=['/cygdrive/c/Program Files (x86)/Microsoft SDKs/MPI/Lib/x64/msmpi.lib'] --with-mpi-mpiexec="/cygdrive/c/Program Files/Microsoft MPI/Bin/mpiexec.exe" --with-debugging=0 -CFLAGS='-O2 -MD -wd4996' -CXXFLAGS='-O2 -MD -wd4996' --with-file-create-pause=1

configure はそこそこ時間がかかる。終わったら make を実行。

$ make PETSC_DIR=`pwd` PETSC_ARCH=arch-mswin-c-opt all

問題なく終わったら、テストを実行。

$ make PETSC_DIR=`pwd` PETSC_ARCH=arch-mswin-c-opt test

link を元に戻しておく。

$ mv /usr/bin/link-cygwin.exe /usr/bin/link.exe

petsc4py のために以下を実行する。

$ cd arch-mswin-c-opt/lib
$ cplibpetsc.lib petsc.lib

mpi4py

mpi4py を pip でインストールする。

$ pip install mpi4py

petsc4py

ソースコードを ここ からダウンロードして展開する。

コマンドプロンプトを起動し、環境変数を設定する。

>set PETSC_DIR=C:\cygwin64\home\<ユーザー名>\petsc\petsc-3.7.3
>set PETSC_ARCH=arch-mswin-c-opt

ディレクトリに移動。

>cd petsc4py-3.7.0

conf/baseconf.py の 186 行目にある以下の行をコメントにする。

petsc_lib['runtime_library_dirs'].append(self['PETSC_LIB_DIR'])

ビルドスクリプトを実行する。

>python setup.py build build_ext --libraries="libf2cblas libf2clapack msmpi" --library-dirs="C:/Program Files (x86)/Microsoft SDKs/MPI/Lib/x64;%PETSC_DIR%/arch-mswin-c-opt/lib" --include-dirs="%PETSC_DIR%/arch-mswin-c-opt/include;%PETSC_DIR%/include;C:/Program Files (x86)/Microsoft SDKs/MPI/Include"

…で、ここで上手くいかない。以下のエラーが出る。

Unable to find vcvarsall.bat

参考

Python で以下を実行。

from distutils.msvccompiler import *
get_build_version()

ここでは 14 が出た。14 は Visual Studio 2015 のバージョンらしい。Python でコンパイラが必要になると、Python をコンパイルしたコンパイラ以上のバージョンを要求するらしく、ここでは Visual Stduio 2010 (バージョン 10) に相当する Windows SDK を用いようとしているため、コンパイラを認識してくれないらしい。

バージョンの判断は以下の部分で行われている。

C:\Anaconda3\Lib\distutils\_msvccompiler.py

C:\Anaconda3\Lib\distutils\_msvccompiler.py

def _find_vcvarsall(plat_spec):
   ...
   if version >= 14 and version > best_version:

つまり、14 以上でないとダメ。この部分を書き換えてしまえばよい。

強引に進めると、次のエラーが出る。

LINK : fatal error LNK1117: syntax error in option 'MANIFEST:EMBED,ID=2'
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\Bin\\
amd64\\link.exe' failed with exit status 1117

以下のように書き換え。

_msvccompiler.py

    def initialize(self, plat_name=None):
        ...

        #self.ldflags_shared = [*ldflags, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO']
        self.ldflags_shared = [*ldflags, '/DLL', '/MANIFESTUAC:NO']

次のエラー。

LINK : fatal error LNK1181: cannot open input file 'ucrt.lib'

書き換え。

_msvccompiler.py

        if not self._vcruntime_redist:
            #ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib'))
            ldflags.extend(('/nodefaultlib:libucrt.lib', '/nodefaultlib:ucrt.lib'))

エラー。

MSVCRT.lib(MSVCR100.dll) : error LNK2005: fprintf already defined in LIBCMT.lib(
fprintf.obj)

上で書き換えた部分を再度書き換え。

_msvccompiler.py

        if not self._vcruntime_redist:
            #ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib'))
            #ldflags.extend(('/nodefaultlib:libucrt.lib', '/nodefaultlib:ucrt.lib'))
            ldflags.extend(('/nodefaultlib:libucrt.lib', '/nodefaultlib:ucrt.lib', '/nodefaultlib:libcmt.lib'))

注意: 適当に書き直しているが、あとで問題が起る可能性あり。Cython コードのコンパイルの時に libcmt.lib の設定があるとマズイらしい。

最後までいけたら、インストールを実行。

>python setup.py install

ちゃんとインストールされているか確認。

>pip search petsc4py
petsc4py (3.7.0)  - PETSc for Python
  INSTALLED: 3.7.0 (latest)

テスト

petsc_test.py

from petsc4py import PETSc
rank = PETSc.COMM_WORLD.getRank()
num_ranks = PETSc.COMM_WORLD.getSize()

x = PETSc.Vec().createMPI(4) # VecCreateMPI: Creates a parallel vector.  size=4
x.setValues([0,1,2,3], [10,20,30,40]) # VecSetValues: Inserts or adds values into certain locations of a vector.  x[0]=10, x[1]=20, x[2]=30, x[3]=40

print ('Rank',rank,'has this portion of the MPI vector:', x.getArray() ) # VecGetArray: Returns a pointer to a contiguous array that contains this processor's portion of the vector data.

vec_sum = x.sum() # VecSum: Computes the sum of all the components of a vector. 10+20+30+40=100

if rank == 0:
    print ('Sum of all elements of vector x is',vec_sum,'and was computed using',num_ranks,'MPI processes.')

実行。

$ mpiexec -np 2 python petsc_test.py
Rank 1 has this portion of the MPI vector: [ 30.  40.]
Rank 0 has this portion of the MPI vector: [ 10.  20.]
Sum of all elements of vector x is 100.0 and was computed using 2 MPI processes.

参考