実行モジュールを別のシステムで動かす (Linux)

対象 a.out 実行バイナリ Linux

 PGI コンパイラを実装しているシステム上で作成した実行モジュール(バイナリ)を他の同一OSのシステムにコピーして実行させる際の方法、注意事項を説明します。こうした状況は、一般にPCクラスタ上のマスタノードで作成された実行モジュールを他のスレーブノード上で実行させるような場合にあたります。これは技術的に言えば、PGIの専用 shared library を取り扱い方を説明するものです。なお、Windows環境では、生成された実行モジュールは、デフォルトでスタティック形式のビルドを行っておりますので、以下に述べるような DLL(shared library)ライブラリのコピー等は必要ありません。他のシステムにコピーして、そのまま実行できます。
2018年11月26日更新

PGI コンパイラで生成したモジュールを別のシステムで動かす方法

 一般的な 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. PC クラスタの場合は、システム設計時に クラスタ全てのノードからアクセスできる共有領域(NFS領域)にシステム管理領域(パーティション)を設け、その配下に、マスタ・ノードからPGI ソフトウェアをインストールする方法
  2. 各マシン(スレーブ)上でローカルに、かつ明示的に /opt/pgi のディレクトリを作成し、PGI をインストールしたマシンから、PGI 関連の dynamic shared library をコピーする方法
  3. 各マシン(スレーブ)上でローカルに、、外部 dynamic shared library を保存する ディレクトリを作成して、この配下に PGI をインストールしたマシンから、PGI 関連の dynamic shared library をコピーする方法

【システム上で設定する方法】

  1. プログラムのリンケージのレベルで、dynamic shared library をリンクせず、スタティックなライブラリをリンクし、実行モジュールを作成する方法(Linux 32ビット環境のみで有効)

【参考情報】
PGI Server ライセンス製品の使用を例として、32bit マシンと 64bit マシンの混在時の PGI 環境変数の設定例をこちらのページで説明しています。ノードロックの PGI Workstation ライセンスを複数お持ちのお客様は、環境変数の設定方法に関して参考になるかと思います。

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.1016.1~16.10 と置き換えてください。
 PGI 2017 (17.1~17.10) の場合は、以下の 18.1017.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 のローディングに対しては、システム側でその設定をしておきます。その方法として以下の二つの方法があります。どちらかの方法で実施して下さい。

  1. LD_LIBRARY_PATH 環境変数に PGI の dynamic shared library の場所を含める。sh 型のシェルの場合は、"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{インストール先ディレクトリ}/lib" と入力する。
  2. /etc/ld.so.confを修正して、/sbin/ldconfig システム・ユーティリティを使用して、PGI の dynamic shared library を登録する。(注: ユーティリティの実行には、root ユーザ権限が必要です。)

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) の方法をお勧めします。