PGIコンパイラのリンク時のトラブル等に関するFAQ

 本ページは、PGIコンパイラを使用して、コンパイル後のリンクフェーズに生じる問題等に関する FAQ のページです。
© 株式会社ソフテック

PGIコンパイラのリンク時のトラブル等に関する FAQ

 

 リンケージに関する質問への回答

Question  1. Linux 上の PGI 11.0 と 11.1を使用すると、/usr/bin/ld: /opt/pgi/linux86-64/11.1/lib/libpgbind.a(bindsa.o): relocation R_X86_64_PC32 against undefined symbol `syscall@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC でエラーが生じます。回避策は?

Answer

PGI 2011 (11.0) から、Linux 上のリンク処理において、OpenMP ライブラリをデフォルトでリンクするように変更しました。これに伴い、NUMAベースの Linux システムにおいては、CPUコアとメモリのバインディングをハンドリングする libpgbind ライブラリもデフォルトでリンクされるようになりました。しかし、Shared ライブラリを作成するような場合に、ibpgbind.a ライブラリの正しい fpic バージョンを探すことができず、こうしたエラーを生じさせています。PGI 11.2 のリリースからこの問題を排除するために修正を行っていますので、11.2 にリビジョンアップできる方は、新しい PGI リビジョンを実装してご使用下さい。なお、この問題は、Shared ライブラリを作成しない場合は、生じません。 もし、PGI 11.0/11.1 でこの問題を回避したい場合は、リンク時のオプションに -nomp を加えてリンケージ処理を行って下さい。

Question  2. PGIコンパイラを使用して、インテル®の MKL ライブラリのリンク方法を教えて下さい。

Answer

Intel® Math Kernel Library (「MKL」と言う。) は、インテルのマイクロプロセッサ用に高度に最適化された数学関数からなるライブラリです。Intel MKL 10.1リリース以降、PGIコンパイラは、MKL ライブラリをユーザプログラムにリンクできるようになりました。インテル MKL 10.1 以降の資産をお持ちのユーザは、PGIコンパイラ環境上で、Intel® MKL ライブラリを活用できます。 この詳細については、技術コラム「PGIコンパイラによるインテル MKL ライブラリのリンク方法」で説明していますので、ご参照下さい。また、 関連 FAQを以下に示します。

Question  3. Linux の環境変数 LD_LIBRARY_PATH に設定した外部ライブラリのパスが、PGIコンパイラのリンク時に反映されません。

Answer

PGIコンパイラでは、Linux 上の環境変数 LD_LIBRARY_PATH に設定している外部ライブラリの「パス名」のリストをリンク時の -L{ライブラリパス}の中に反映するような設定となっていません。従って、リンクフェーズで外部ライブラリの場所を指定するためには、必ず -L オプションを使用して指定しなければなりません。一般に、環境変数 LD_LIBRARY_PATH は、Linux 上の環境変数であり、実行時にダイナミックローダで必要なライブラリを検索するためのもので、検索対象となるライブラリパス名を指定するものです。この内容をリンク時にも反映するコンパイラシステムもありますが、PGI ではリンク時には使用しません。その理由として、LD_LIBRARY_PATH は、ユーザが勝手に様々なものを指定する可能性が高い環境変数であることが挙げられます。この LD_LIBRARY_PATH で定義されたパス名のリストの全てを、リンク時の -L オプションリストに追加指定されると、リンク・ライブラリ・パスの「並び順序」によっては、適切な PGI 専用のシステム・ライブラリが参照(未定義関数の解決が)できない場合が出てきます。リンク時におけるライブラリ・パスの並びは、非常にセンシティブです。従って、PGI のリンク時のデフォルトでは、LD_LIBRARY_PATH のリストは検索対象とはしません。環境変数 LD_LIBRARY_PATH の役目は、ランタイムの未解決 shared library を検索するためのものと捉えて下さい。

Question  4. Linux 上の GNU やインテル社のコンパイル環境で使用されている LIBRARY_PATH 環境変数で指定したライブラリ・パスがあります。この外部ライブラリのパスをデフォルトで、 PGI のリンク時のオプションである -L{ライブラリパス} に反映したいのですが。

Answer

PGIコンパイラ・システムのオプションのデフォルト設定を行うには、コンパイラ内部の変数値を操作する必要があります。ご質問の内容は、具体的に言えば、Linux 上の環境変数 LIBRARY_PATH の値(パス名のリスト)を、リンク時のオプションである -L{ライブラリパス} に反映するようにすることです。これを行うためには、ルート権限で、PGIコンパイラの bin ディレクトリ配下に、初期設定ファイル siterc を作成し、その中にその設定を行う必要があります。siterc とは、サイト全体(全ユーザ)に反映される、ローカルな初期設定 rc ファイルを言います。このファイルは、以下に示すように、個々のリビジョン(例えば PGI 11.9 ) の bin ディレクトリ配下に置く必要があります。
【注意】PGIのバージョンアップする度に、siterc ファイルを所定の場所に置く必要があるため、忘れないようにすること。

(64ビット)
 $PGI/linux86-64/{revision}/bin (例えば、PGI 11.9 の場合 /opt/pgi/linux86-64/11.9/bin)
(32ビット)
 $PGI/linux86/{revision}/bin (例えば、PGI 11.9 の場合 /opt/pgi/linux86/11.9/bin)

siterc ファイル(コンパイラへの変数設定値を指示するファイル)の記述は、以下のように行います。こうして記述した siterc ファイルを上記の所定の場所に置くことによって、この内容がその後のコンパイル・リンク時に反映されます。なお、実行時のランタイム shared library の検索については、環境変数 LD_LIBRARY_PATH の内容を反映しますので、実行時においては、この環境変数の設定は必ず必要です。

# Added by SofTek
# get the value of the environment variable LIBRARY_PATH
variable LIBRARY_PATH is environment(LIBRARY_PATH);

# split this value at colons, separate by -L, prepend 1st one by -L
variable library_path is
default($if($LIBRARY_PATH,-L$replace($LIBRARY_PATH,":", -L)));

# add the -L arguments to the link line
append LDLIBARGS=$library_path;

例えば、インテル® MKL ライブラリの場合は、リンク時に -L/opt/intel/Compiler/{version番号}/{???}/mkl/lib/em64t 等の -L オプション の指定が必要ですが、こうしたMKLのライブラリ・パスは、環境変数 LIBRARY_PATH に定義されていますので、上記の siterc ファイルと同じものを設置すると、-Lオプションの指定は必要なくなります。

(コンパイル・リンクオプション例) -L オプションの指定は必要ない
pgfortran -fastsse -Minfo -mp test.f90 -lmkl_intel_lp64 -lmkl_pgi_thread -lmkl_core

Question  5. Linux 上で、-Bstatic オプションを使ってリンクすると、/usr/bin/ld: cannot find -lpthread と言うエラーメッセージが出ます。

Answer

このエラーメッセージは、リンク時に、libpthread.a と言う静的ライブラリが見つからなかったと言う意味となります。一般に、libpthread.a は PGI のライブラリルーチンではなく、GNU glibc のシステム・ライブラリ・ルーチンを使用します。今回の問題は、コマンド行の中に、-Bstatic オプションを入れた場合に発生することがあります。

$ pgf90 -fastsse  himenoBMTxp_omp.f90 -Bstatic
/usr/bin/ld: cannot find -lpthread

-Bstatic オプションは、 明示的に、static libraries を使用して静的リンク形式の実行バイナリを作成するように指示するものです。従って、この問題は、 Linux システム内に libpthread.a と言う「静的」なスレッド・ライブラリが実装されていないことを意味しています。(リンク時に探したが、存在しなかったと言う意味)。
この問題の回避策を述べます。
システム内に GNU glibc の static library を導入する必要があります。 例えば、Red Hat/Cent OS/Fedora 系の Linux であれば、glibc-static パッケージをルート権限で yum を使用して探してください。現在の Linux distributions は、デフォルトで静的な glibc ライブラリを実装しません。明示的にシステムに導入する必要があります。(他の distributionの場合は、 glibc-static を探してください。ちなみに、SUSE 系は、glibc-devel-static と言うパッケージ名称です。 )今回の問題は、最近の Linux distributions は GNU glibc の static library をデフォルトで実装しなくなったことに原因があります。(過去の Linux distributions はデフォルトでも実装していました。)

(パッケージが存在するかどうか探す)
$ yum search glibc-static

glibc-static.i686 : C library static libraries for -static linking. (32ビット版)
glibc-static.x86_64 : C library static libraries for -static linking.(64ビット版)

(インストール)
$ yum install glibc-static.x86_64
$ yum install glibc-static.i686 

これで、システム上に64bit版の glibc 静的ライブラリ(libpthread.aを含む)が実装されました。必要であれば 32bit版のライブラリも実装してください。その後、再度、コンパイルとリンクを行うと正常に実行バイナリが生成されるはずです。なお、コンパイル・リンク時に以下のメッセージが出ることがありますが、これは無視してください。

/usr/lib64/libpthread.a(libpthread.o): In function `sem_open':
(.text+0x764d): warning: the use of `mktemp' is dangerous, better use `mkstemp'

なお、他の代替策としては、動的なリンク形式の実行バイナリでも良いのであれば、-Bstatic をリンクオプションから除いて下さい。この場合は、正常にリンクされるはずです。また、PGI 提供のライブラリは静的ライブラリをリンクし、Linux の GNU システム・ライブラリは動的リンク形式のライブラリを使う形式の実行バイナリも作成出来ます(一般にはこれが良いと思います)。この場合は、-Bstatic の代わりに -Bstatic_pgi オプションをお使いください。このオプションに変えると、今回のケースは正常にリンク出来るようになります。