a.out 実行バイナリ Linux
PGI コンパイラを実装しているシステム上で作成した実行モジュール(バイナリ)を他の同一OSのシステムにコピーして実行させる際の方法、注意事項を説明します。こうした状況は、一般にPCクラスタ上のマスタノードで作成された実行モジュールを他のスレーブノード上で実行させるような場合にあたります。これは技術的に言えば、PGIの専用 shared library を取り扱い方を説明するものです。なお、Windows環境では、生成された実行モジュールは、デフォルトでスタティック形式のビルドを行っておりますので、以下に述べるような DLL(shared library)ライブラリのコピー等は必要ありません。他のシステムにコピーして、そのまま実行できます。
2018年11月26日更新
一般的な Linux 上の実行バイナリ形態と同様に、PGI で生成された実行モジュール(a.out) は、全て実行に必要なライブラリを含めた「静的」な実行形式では生成されていません。いわゆる、ダイナミックな共有ライブラリを使用する形式になっており、実行時にその dynamic shared library (libxxx.so の形式のファイル) をシステム側から取り込み、動作する形式となっています。例えば、PGI 関連の dynamic shared library として、libpgc.so があります。この libpgc.so は、PGI の Run-time library であり、PGI がインストールされている領域 (32bit 環境では、/opt/pgi/linux86/16.10/lib(libso)、あるいは 64bit 環境では、/opt/pgi/linux86-64/16.10/lib(libso) ) に存在します。(この例は、PGI 16.10 の場合。その他のバージョンの場合は、太字部分が当該バージョン番号に変わります。)PGI コンパイラ・ソフトウェアがインストールされているマシン上での実行は、このライブラリのパス /opt/pgi/linux86/16.10/lib (or libso) 内のライブラリを実行時に読み込みますが、PGI をインストールしていない異なるマシンでは、この shared library をシステム内に有していないため、下記のような エラーが出ます。
error while loading shared libraries: libpgc.so:
ちなみに、実行モジュールの中でどのような dynamic shared library が使用されているかは、以下のコマンド (ldd) で確かめることができます。PGI 関連の libpgc.so がリンクされることが分かります。このファイルは、PGI をインストールしたマシン上でしか存在しません。以下の例に示すように、他にもダイナミックにリンクされる PGI の shared library が存在します。
(64bit Linux 上の例で、OpenMP 並列化された実行モジュール) [kato@photon29 Himeno]$ ldd a.out DISTRIB_DESCRIPTION="Ubuntu 14.04 LTS" linux-vdso.so.1 => (0x00007ffffe0da000) libpgf90rtl.so => /usr/pgi/linux86-64/16.10/lib/libpgf90rtl.so (0x00007fc54d3f5000) libpgf90.so => /usr/pgi/linux86-64/16.10/lib/libpgf90.so (0x00007fc54cf5b000) libpgf90_rpm1.so => /usr/pgi/linux86-64/16.10/lib/libpgf90_rpm1.so (0x00007fc54ce59000) libpgf902.so => /usr/pgi/linux86-64/16.10/lib/libpgf902.so (0x00007fc54cd46000) libpgftnrtl.so => /usr/pgi/linux86-64/16.10/lib/libpgftnrtl.so (0x00007fc54cc11000) libpgmp.so => /usr/pgi/linux86-64/16.10/lib/libpgmp.so (0x00007fc54ca91000) libnuma.so => /usr/pgi/linux86-64/16.10/lib/libnuma.so (0x00007fc54c990000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc54c758000) libpgc.so => /usr/pgi/linux86-64/16.10/lib/libpgc.so (0x00007fc54c5e1000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fc54c3d9000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc54c0d2000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc54bd0d000) /lib64/ld-linux-x86-64.so.2 (0x00007fc54d51c000)
PGI ソフトウェアがインストールされているマシン上で作成した実行モジュールを別のマシン上で動かしたい場合には、その対策が必要です。このような場合の典型的な例は、PCクラスタ上のスレーブ・マシン上での実行において遭遇します。また、別のシステム上で単独で動かしたい場合も以下に述べる対策が必要です。
ここで述べる前提として、「別のマシン」の意味は、PGI コンパイラが実装されている(コンパイルする)マシンの Linux kernel のバージョン並びに glibc のバージョンと互換性を有するマシンと言う意味です。全くかけ離れたバージョンのマシン間では、動作しないことがありますので、その際はお問合せください。Linux の glibc のバージョンを知るためのコマンドは、ルート権限で "/lib/libc.so.6" あるいは "/lib64/libc.so.6" を実行してください。
PGI コンパイラがインストールされているマシン以外の「別のシステム」で実行モジュールを動かす典型的な例は、PCクラスタのスレーブ・ノード上での場合です。すなわち、PGI コンパイラは、マスタ・ノード上にインストールして、実行はスレーブ・ノード上で行う等の場合です。クラスタに限らず、「別のシステム」と言うのは、こうした同じような状況を意味すると捉えてください。
対策としては、システム上でその設定をする方法と、リンク・オプションだけで別のシステムで動く実行モジュールを作成する二種類の方法があります。ここでは、以下の方法をそれぞれ説明します。最も簡単な対策をお選びください。
【システム上で設定する方法】
【システム上で設定する方法】
1. 全てのノードからアクセスできる共有領域(NFS領域)に PGI をインストール
この方法は、PCクラスタ構築時(設計時)に行わなければならないことに留意してください。実施することは、クラスタ全てのノードからアクセスできる共有領域(NFS領域)にシステム管理領域(パーティション)を設けることです。例えば、この NFS 領域のパーティションを仮に /export とした場合、PGI ソフトウェアのインストールを /export/pgi 配下に行うことで、全てのノードから /export/pgi 配下の PGI 関連の動的ライブラリをアクセスすることができます。なお、PGI ソフトウェアのインストールはマスタ・ノード上で行い、コンパイル作業もここで行うことを前提にしています。この対策のシステム的な作業は、これだけで済みます。
なお、各ユーザのシェルの環境変数の設定は、全てのノードで同じ形を取ります。例えば、この場合は、以下のような形態になります。以下の例は、PGI 18.10 の場合) 関連する FAQ ページはこちら。
(64bit Linux環境の場合) csh または、tcsh の場合、$HOME/.cshrc 等 setenv PGI /export/pgi (コンパイラの installation directoryを定義) set path = ( $PGI/linux86-64/18.10/bin $path ) setenv MANPATH “$MANPATH“:$PGI/linux86-64/18.10/man setenv LM_LICENSE_FILE $PGI/license.dat sh または、bash の場合、$HOME/.bashrc 等 export PGI=/export/pgi (コンパイラの installation directoryを定義) export PATH=$PGI/linux86-64/18.10/bin:$PATH export MANPATH=$MANPATH:$PGI/linux86-64/18.10/man export LM_LICENSE_FILE=$PGI/license.dat
2. 各マシン(スレーブ)上でローカルに、 /opt/pgi (PGI のインストールdirectory) のディレクトリを作成
この対策は、実行モジュールを動かしたいマシン上で、ローカルにマスタノードと同じ「/opt/pgi のディレクトリ」を作成し、PGI をインストールしたマシン(以下、「マスタ・ノード」と称する)のディレクトリ構造と同じものを作ることです。但し、構造は同じにするだけで、マスタ・ノードからコピーするのは、PGI の dynamic shared library だけです。ディレクトリの名前は、マスタ・ノードと全く同じものを作成してください。なお、作成した directory のパーミッションは 0777(あるいは 0775) としてください。
各マシン(スレーブ)上で、ルート権限で以下の directory を作成する。 PGI 2016 (16.1~16.10) の場合は、以下の 18.10 を 16.1~16.10 と置き換えてください。 PGI 2017 (17.1~17.10) の場合は、以下の 18.10 を 17.1~17.10 と置き換えてください。 【 64ビットPGIソフトウェア環境 】 mkdir /opt/pgi/linux86-64/18.10/lib マスタノードから PGI の64ビット dynamic shared library をを同じディレクトリ構造を持つ同じ場所に コピーする。コピーするファイルは、以下のとおり。(以下に説明する REDIST directory 配下のもの全てをコピーする)
各ユーザのシェルの PGI 関連の環境変数 (PGI、PATH) の設定は、マスタ・ノードでの設定と全く同じ形を取ります。
PGI ランタイムライブラリ( dynamic shared library)は、以下の REDIST dierectory 配下に配置されています。 PGI ランタイムライブラリは、他のマシンで動作させるために必要なライブラリで、PGI ライセンス規約上、コピーしてご利用いただいても問題のないファイルです。
以下の REDIST ディレクトリでは、シンボリックリンクされたファイルが置かれており、
実体ファイルは別の場所に存在します。実体ファイルをコピーするには、cp -L オプションを使い、
一旦、実体ファイルをコピーする場所に待避してから tar 等でアーカイブ化して下さい。
【64bit Lnux の場合】、
/opt/pgi/linux86-64/18.10/REDIST (64bit環境用)の例
$ ls
libaccapi.so@ libaccncmp.so@ libcudafor80.so@ libpgc.so@ libpgmp.so@ libpgnod_prof_mvapich2.so@
libaccapimp.so@ libaccnmp.so@ libcudafor90.so@ libpgf90.so@ libpgnod_prof.so@ libpgnod_prof_openmpi.so@
libaccg.so@ libblas.so@ libcudafor91.so@ libpgf902.so@ libpgnod_prof_g.so@ libpgnod_prof_pfo.so@
libaccg2.so@ libcublasemu.so@ libcudaforblas.so@ libpgf90_prof.so@ libpgnod_prof_inst.so@ libpgnod_prof_time.so@
libaccg2mp.so@ libcudacemu.so@ libcudapgi.so@ libpgf90_rpm1.so@ libpgnod_prof_mpi.so@ libpgnuma.so@
libaccgmp.so@ libcudadevice.so@ libhugetlbfs_pgi.so@ libpgf90_rpm1_p.so@ libpgnod_prof_mpi2.so@
libaccn.so@ libcudafor.so@ liblapack.so@ libpgf90rtl.so@ libpgnod_prof_mpi3.so@
libaccnc.so@ libcudafor2.so@ libpgatm.so@ libpgftnrtl.so@ libpgnod_prof_mvapich.so@
$ pwd
/usr/pgi/linux86-64/18.10/REDIST
$ mkdir /tmp/PGIshared (コピーする先の directoryを作成する)
$ cp -L * /tmp/PGIshared/ (cp を行う際、-Lオプションを付けてください)
$ tar で纏める
なお、過去のPGI バージョンでは、PGI Accelerator Compiler がリリースされてから、
「PGIアクセラレータ用」の REDIST-RLR ディレクトリが用意されている場合があります。
この中に含まれている shared libary も、上記の同じ場所(例/opt/pgi/linux86-64/18.10/lib)に
コピーして下さい。
3. 各マシン(スレーブ)上でローカルに、外部 dynamic shared library を保存する ディレクトリを作成
この対策は、上記の (2) とほぼ同じ対策ですが、PGI の dynamic shared library をシステム専用のライブラリ保存領域にコピーしておくことです。このためには、マシン毎ローカルに、、外部 dynamic shared library を保存する ディレクトリを作成して、この配下にPGI をインストールしたマシンから、PGI 関連の dynamic shared library をコピーする作業が必要です。なお、作成した directory のパーミッションは 0777(あるいは 0775) としてください。例えば、この領域を /usr/export/pgi として作成し、この配下に PGI 関連の dynamic shared library をコピーしておくことになります。
各マシン(スレーブ)上で、ルート権限で以下の directory を作成する。 他のバージョンの場合は、以下の太字番号 18.10 を当該バージョン番号に置き換えてください。 【64bit Linux の場合】 mkdir /usr/export/pgi/linux86-64/18.10/lib マスタノードからPGIの64ビット dynamic shared library を同じディレクトリ構造を持つ同じ場所に コピーしてください。コピーするファイルは、上記に示した REDISTディレクトリ配下の ライブラリです。
実行時の dynamic shared library のローディングに対しては、システム側でその設定をしておきます。その方法として以下の二つの方法があります。どちらかの方法で実施して下さい。
4. プログラムのリンケージのレベルで、スタティックなライブラリをリンクし、実行モジュールを作成する(32bit Linux only)
この対策は、PGI 2017 以降、32ビットコンパイラ環境を提供しませんので適用できません。古いPGI環境においては、システム管理上の作業は伴わず、ユーザサイドだけで行うことができる対策です。但し、32ビット Linux 環境のみで利用可能です。実行モジュールの作成において、dynamic shared library をリンクせず、同じスタティックなライブラリをリンクしておく方法です。これは、最も手軽な方法ですが、全てのライブラリを含んで実行モジュールが作成されるため、モジュールのサイズが大きくなるデメリットがあります。サイズを気にしないのであれば、この対策を施すことで別のシステム上で動作可能です。コンパイル時のリンク・オプションに以下の -Wl,-Bstatic を付加してコンパイルしてください。なお、PGI 5.1 から同機能オプションである -Bstatic オプションが提供されました。関連情報として、こちらのページもご覧ください。
pgf90 {other compile options} -Wl,-Bstatic test.f あるいは pgf90 {other compile options} -Bstatic test.f (PGI 5.1以降)
上記で生成された実行モジュールを使用することで、、dynamic shared library を気にすることなしに実行することができます。また、別のマシンでの各ユーザのシェルの PGI 関連の環境変数 (PGI、PATH) の設定は必要ありません。
【既知の制約事項】
64bit OS環境において、-mcmodel=meidium -Bstatic オプションにて静的なリンク実行モジュールを作成する際、「リンク時」のエラーが生じる場合があります。 64ビット Linux が提供する静的システムライブラリの中の一部のモジュールが 64bit でオブジェクトが生成されていないことによるものです。(PGI の問題ではありません) 即ち、完全な形で 64ビット静的システムライブラリが提供されていない場合があるため、-mcmodel=medium において-Bstatic はサポートしておりません。この場合は、上記の (3) の方法をお勧めします。