本ページは、PGIコンパイラを使用して、コンパイル/リンク/プログラム実行時の問題に対する FAQ のページです。
© 株式会社ソフテック
コンパイル/リンク/プログラム実行時の問題への回答
1. PGI コンパイラで作成した実行モジュールは他のマシンでも実行できますか?
実行できます。他のマシンで実行するための技術的な詳細情報は、こちらのページをご覧ください。
2. PGI コンパイラにおける、動的リンク、静的リンクとはどのような意味でしょうか
ユーザプログラムをコンパイルし、実行モジュールを作成する際にインクルードするライブラリのリンク方法を指します。例えば、ユーザプログラム中にスレッド・ライブラリを使用することが明示されている場合、動的リンクの場合は、スレッド・ライブラリを使用する時点でライブラリが読み込まれるようになります。逆に静的リンクの場合は、ユーザプログラム中のスレッド・ライブラリ使用部分に、コンパイル時にスレッド・ライブラリが埋め込まれます。一般に、静的リンクで必要なライブラリ(static
library) の名前は、一般に libxxx.a の形式 (.a) です。それに対して、以下で説明する動的リンクで必要なライブラリの名前は、一般に、libxxx.so の形式で、dynamic shared library と言われております。参考情報として、こちらのページをご覧ください。
動的リンクは、必要なライブラリを使用する時点でリンクするため、実行バイナリファイルサイズを小さくすることができ、使用メモリ量も減らすことが可能です。PGI コンパイラで生成される実行モジュールは、動的リンクを暗黙に行ないます。ただし動的リンクを行なった場合(これはデフォルトです)、作成された実行バイナリファイルを他のマシンで実行できない問題や、1 プロセスあたり、1GB 以上のメモリを使用できない問題が発生します。 この解決策の詳細については、こちらのページをご覧ください。
3. 1GB を越えるメモリを使用する Fortran プログラムを実行できますか (32bit版 使用時)
可能です(上限は 2GB程度です)。コンパイル・オプション "-Wl,-Bstatic" を用いて静的ライブラリを用いた実行モジュールを作成する必要があります(PGI 5.1 から同機能オプションである -Bstatic オプションが提供されました)。本オプションは、コンパイラが暗黙に用いる動的ライブラリを用いず、強制的に全て、スタティックなライブラリを用いた 静的リンクを行います。いわゆる、Linux上における 1GB の壁は、動的ライブラリをメモリマップ上に置くポイントが、1GB ポインタであることによる問題です。動的ライブラリを用いない静的リンクにしますと、この制約がなくなります。なお、1GBを越えるメモリ量を扱う Fortran プログラムを動かすためには、マシン自体にも十分なメモリ量(物理メモリ + swap メモリで 1GB 以上)を確保することも必要です(プログラムが必要とするメモリ量よりも、物理メモリ + swap メモリ量が少ないと正常に動作しません)。
また、32ビットLinux 上のメモリ管理仕様の一般的知見として、 mcmodel=small の場合、1 回当たりの malloc サイズが
128KB 以下の操作でスタックしていくメモリ使用総量の上限が 1GB まで、128KB 以上のスタックの集積総量の場合は、 2GB まで使用できると言う制約があります。
4. 2GB を越えるメモリを使用する C/Fortran プログラムを実行できますか (64bit 版 使用時)
x86-64(AMD64) CPU 用の C、FORTRAN77、Fortran90 64bit コンパイラ release 5.2 以降で可能ですなお、2GB を越えるメモリ量を扱うプログラムを動かすためには、マシン自体にもプログラムに見合う十分な実メモリ量を確保することも必要です。 仮想メモリ+ Swap エリアを利用した実メモリ容量を超える大きなプログラムの実行は、性能が著しく低下します。ちなみに、2GB を超えるプログラムのコンパイル・オプションは次のとおりです。この詳細に関しては、技術情報(TIPS) のこちらのページでご覧ください。
pgf90 -mcmodel=medium -Mlarge_arrays test.f あるいは、 pgf90 -tp {k8-64:p7-64} -mcmodel=medium -Mlarge_arrays test.f
5. Linux kernel 2.4 で対応している Large File System(2GB 以上のファイル操作)に関して、対応していますか
2GB 以上のファイルの取扱いに関しては、 PGI 5.0 以降の pgf77、pgf90 においてデフォルトで対応しております。リリース4以前の PGI コンパイラは 3.3 以降で、Large File System(2GB 以上のファイル操作)をサポートしております。リンク時に以下のオプションを付けて実行モジュールを作成してください。但し、いずれの場合も、Linux のファイルシステム機能が、2GB 以上のファイル操作が可能な実装状況が必要です。
-Mlfs または -L$PGI/linux86/{Release_number}/liblf
(一例:-L/usr/pgi/linux86/6.2/liblf)
6. コンパイル時に以下のようなエラーが出てしまいます。バグでしょうか
:Assembler messages: :Error: no such instruction: `cvttsd2si -32(%ebp),%eax'
:Assembler messages: :Error: no such instruction: `cvttsd2si -32(%ebp),%eax'
"cvttsd2si" 命令は、Pentium 4 用の SSE2 命令です。Pentium 4 上で pgf77 コマンド等でコンパイルすると自動的にこの命令が埋め込まれる場合があり、SSE2 インストラクションを有していない Pentium 4 以外の下位 Pentium の CPU では正常に動作しません。また、Pentium 4 マシンでコンパイル時に cvtssd2si 関係のエラーが出る場合は、Pentium 4 用の命令を(カーネルが)認識できていない環境(古いRed Hat Linux の環境等)をお使い頂いていることが原因です。
"-tp p6" オプション (Pentium III まで対応の実行コードを生成します)をつけて頂ければ、上記エラーは解決できますが、Pentium 4 の SSE2 命令の機能が生かし切れなくなります(Pentium 4 で実行の際)。
Red Hat のバージョンが、7.1 以降でしたら SSE 命令に対応しますので、 SSE 命令を活用する場合は、これらバージョンをお使い頂ければと思います。以下にRed Hat Linux の SSE 命令対応表を記します(PGI コンパイラ、リリース 3.2 以降は全ての SSE 命令に対応しています)。また、現在のプロセッサのハードウェアが備える SSE 機能対応表をこちらのページに用意しました。
7. コンパイル・オプションの -fastsse 使用して Makefile により実行モジュールを作成しようとすると、リンク時に以下のような "__mth_i_xxx" のエラー出ます
stream_d.o: In function `MAIN_':
stream_d.o(.text+0x851): undefined reference to `__mth_i_idnintx'
stream_d.o(.text+0x95f): undefined reference to `__mth_i_idnintx'
stream_d.o: In function `realsize_':
stream_d.o(.text+0x1afa): undefined reference to `__mth_i_dpowix'
stream_d.o: In function `confuse_':
stream_d.o(.text+0x25df): undefined reference to `__mth_i_dcosx'
stream_d.o: In function `checktick_':
stream_d.o(.text+0x269b): undefined reference to `__mth_i_idnintx'
-fastsse のオプションは、コンパイル時だけではなく、リンケージにおいてもオプションを付ける必要があります。リンク時にオプションの設定をしなかったために起こる問題です。Makefile 等で、コンパイル・フラグとリンク・フラグを分けて指定している場合、リンク・フラグにも -fastsse をつけてリンクを実行してください。
8. 自動並列化オプション -Mconcur を指定して、実行モジュールを作成しようとすると、リンク時に、以下のような _mp_???? 等の未定義関数が発生します
stream_d.o: In function `MAIN_':
stream_d.o(.text+0x34a): undefined reference to `_mp_penter'
stream_d.o(.text+0x34f): undefined reference to `_mp_ncpus'
stream_d.o(.text+0x38c): undefined reference to `_mp_lcpu'
stream_d.o(.text+0x427): undefined reference to `_mp_pexit'
stream_d.o(.text+0x44f): undefined reference to `_mp_penter'
-Mconcur オプションは、コンパイル時だけではなく、リンケージにおいてもオプションを付ける必要があります。リンク時にオプションの設定をしなかったために起こる問題です。Makefile 等で、コンパイル・フラグとリンク・フラグを分けて指定している場合、リンク・フラグにも -Mconcur をつけてリンクを実行してください。
9. 内部手続き間のグローバル最適化のオプション -Mipa を使用する際の留意点はありますか
PGI の内部手続き間のグローバル最適化は、リリース 5.2 以降、一度のコンパイル・リンク・フェーズで 1 パスで行いますが、その際、Makefile でコンパイル・フラグとリンク・フラグを分けて指定している場合、リンク・フラグにも必ず、-Mipa=fast,... をつけてリンクしてください。リンケージのフェーズで、最適化の情報をもとに実行モジュールがビルドされますので、リンク時にオプションを指定しなければ、このグローバル最適化はモジュールに反映されません。なお、IPA に関するコンパイル・リンク時のメッセージ情報を表示したい場合は、
-Minfo=ipa を指定してください。
(コンパイルし、*.o のオブジェクトを作成) pgf90 -fastsse -Mipa=fast,inline -c -Minfo=ipa a1.f a2.f (その後、リンクする)
10. リンク時に、以下のような ___rouent 等の未定義関数があると言うメッセージが出ます
Test.o: In function `MAIN_':
Test.o(.text+0x2d): undefined reference to `___rouent'
Test.o(.text+0x121a): undefined reference to `___rouret'
これは、性能解析プロファイラ PGPROF 用のトレースファイルを作成するため、、コンパイラ・オプションに -Mprof を付加して実行モジュールを作成しようとした時に起こる現象です。-Mprof はコンパイル時と、リンク時の両方にオプションとして指定しなければなりません。リンク時にオプションの設定をしなかったために起こる問題です。Makefile 等で、コンパイル・フラグとリンク・フラグを分けて指定している場合、リンク・フラグにも-Mprof をつけてリンクを実行してください。
11. リンカーに未定義の関数参照を無視してリンクするように指示するオプション/フラグはありませんか (Linux)
pgcc -o a.out test.c -Wl,-noinhibit-exec
リンカー ld に対して、指示するオプションの指定方法は、 -Wl,-{switch} です。無視するように指示するフラグ・スイッチは、上記に示した -noinhibit-exec です。
12. リンケージ・マップを出力する方法を教えてください
コンパイル・オプションに、-m をつけてコンパイル・リンクを行ってください。リンク・フェーズが終了した後に、標準出力にリンクマップが出力されます(Linux)
pgcc -m test.c あるいは、 pgcc -Wl,'--print-map' test.c
さらに、リンケージのクロスリファレンスを出力する場合は、以下のように行います。
pgcc -m -Wl,'-cref' test.c あるいは、 pgcc -Wl,'--print-map','-cref' test.c
13. LAPACK を使用する際のリンク・オプションを教えてください
PGI 5.0 以前のバージョンでは、標準の最適化された LAPACK、BLAS がバンドルされています。PGI 5.1 以降のリリースでは、この標準の LAPACK パッケージの他に、AMD 社が提供するアセンブラ SSE/SSE2 インストラクションを使用して性能最適化された BLAS ライブラリ、LAPACK ライブラリ、FFT ライブラリ (AMCL) もバンドルされております。以下に、これらのライブラリをリンクする方法を述べます。
【PGI 標準 LAPACK のリンク】 pgf90 -fastsse test.f -llapack -lblas -lpgftnrtl 【AMD ACMLライブラリの使用】 pgf90 -fastsse -Mcache_align test.f -lacml (-Mcache_align は必ず指定してください) 詳細の説明は、こちらのページへ
14. Sun, SGI 等の UNIX システムで実行した結果と PGI での計算結果が微妙に異なるのですが、どのような原因が考えられますか
x87 の内部レジスタは、80-bit を有し、PGI コンパイラのデフォルトは、x87 の 80-bit 精度での内部演算を行います。一方、レガシーなRISC/UNIX システムでは、64-bit レジスタによる 内部演算処理を行っているため、これによる計算精度の差が出てくるのが一般です。PGIコンパイラは、x86 の内部演算精度を 80-bit, 64-bit, 32-bit に制御することが可能ですので、以下のオプションをセットして、実行結果を比較してください。これに関する詳細な技術情報は、こちらのページをご覧ください。
なお、以下の説明は、当該プロセッサが過去の Pentium III 以前のプロセッサに関しての事項です。これ以降のプロセッサでは x87 系の演算系を使用していないか、そもそも有していません。
-pc 80 (default) -pc 64 (64-bit精度) -pc 32 (32-bit精度) これらは、過去のx86プロセッサ(Pentium 3/4)に対してのみ有効です -Kieee (浮動小数点演算の処理方式を厳密に IEEE 754 に準拠した計算方式を有効化)
15. Fortran プログラムの終了時に出力される FORTRAN STOP を抑制することができますか
環境変数 NO_STOP_MESSAGE を指定して実行してください。値は任意です。
16. Fortranプログラムが何らかの理由(例えばエラーや人為的に終了させるなど)で途中でストップしたとき、その時点までの結果がファイルに書き出されるようにするにはどうすればよいのでしょうか
以下のようなプログラムを実行すると、プログラムは==>マークでストップします。このとき、test1.outには1~10の数字が記入されていますが、test2.outには何も記入されていません。これを、test2.outにもエラーを起こす直前までの結果を書き出させるようにする方法はないのでしょうか?
integer i,j
open(1,file='test1.out',status='unknown')
open(2,file='test2.out',status='unknown')
j=0
do i=1,10
write(1,*) i
enddo
close(1)
do i=1,10
write(2,*) i
==> if(i==5) j=1/j
enddo
close(2)
end
【回答】
これは、ファイルI/O の書き出すタイミングについての問題かと思います。言語処理系における、ファイルI/O のタイミングに関しては、規約はなく、それぞれの実装系に依存します。PGIのファイルI/O
の場合は、I/O性能を向上させるために、一旦、ライブラリ・バッファに入れてから、あるタイミングで、物理的なI/O(ファイルへの実際の書き出し)を行うようになっております。
Fortran 文の I/O -------> Buffer(Memory) ---------> file への入出力
(Logical I/Oと称する) (call flush) (Physical I/Oと称する)
従って、何らかの interrupt がプログラムに生じたばあい、buffering されている内容が書き込まれないという現象が生じます。まさにこれが、二つ目のループの test2.out の書き込みの際に起きているわけです。
バッファ内容をを強制的に書き出すためには、そのためのコマンドをプログラムに入れる必要があります。いわゆる Fortranレベルで使用可能なシステム関数(3F functions) を使用します。
CALL FLUSH(unit番号)
do i=1,10
write(2,*) i
==> if(i==5) j=1/j
CALL FLUSH(2)
enddo
上記の文は、unit番号にかかわる buffer の内容を書き出す指示を出すためのものです。一般には、何かのトラブル時にdebug のために入れることが多い構文となります。特に、下記のように
ループ内に入れた場合はパフォーマンスに影響します。
このような状況を理解していただき、何かあったときに Flush を行うとか、あるいは、一つのプログラムフローの中であるマイルストーンを過ぎた時点で、とりあえず、call flush 文を入れてファイルに書き出しておくというような使い方になります。
他のコンパイラでは、logical I/Oがあった時点で Physical I/O も行うという仕様もありますが、これは、スループット性能を落とす要因となります。PhysicalI/O はレコードサイズが小さければ小さいほど、オーバーヘッドの高い時間の掛かる処理です。PGIと他のコンパイラとは、言語処理系の違いですので、ご理解ください。
何か問題があったときの I/O のトレースを行う場合は、デフォルトで落ちた時点でのファイル内容が見られれば良いと思いますが、何も問題がないときは、性能のほうが重要となりますので、PGIの形式の方が良いです。
状況によって、どちらの形式が良いとは言えませんので、PGIの場合は FLUSH文を入れていただければと思います。なお、FLUSH 文は汎用的に使用できる構文ですので portability 的にも問題ないと思います。
(関連質問)
2007年 10 月 17 日追加
-------------------------------------------------------------------------------
PGI Fortranコンパイラでは、OPEN文などにて開いたファイルにwrite文などにより書き込んだ場合、バッファリングされていると思います。
そのため、プログラムを途中でkillした場合、バッファリングされていたデータがファイルへ反映されませんので(プログラム終了まで実際に書き込まれない場合が多い)、このバッファサイズをPGIコンパイラ側で調整することは可能でしょうか?それとも、これはOS側の設定によるものでしょうか?
また、バッファリングされていてファイルシステムに書き込まれていない場合、CLOSE 文にてファイルを閉じた場合にCLOSE文内部でバッファが確実にflushされるのでしょうか?それとも、PGI コンパイラで用意されているflush文が必須でしょうか?
-------------------------------------------------------------------------------
バッファサイズの変更は、PGI提供のライブラリ・ルーチンを利用して可能です。
一般に Fortran/C/C++ 言語を使用する、User I/O のハンドリングは、コンパイラが提供する I/O ライブラリ-> GNU glibc のロジックを経由して、OS が提供する System Cache の機構を使用して処理します。従って、ユーザプログラムから見た場合、I/O データをハンドリングするのは、PGI 提供の I/O 関係のライブラリが、所望するハンドリングが可能かどうかで決まります。特に、バッファサイズの変更は、Low level では、OS の設定で System Cache 等の設定は可能ですが、これは Linux file system 等の全体の tuning parameter であり、ユーザ個々のプロセスの I/O handling を支配するものではありません。従って、こうしたチューニングは、OS 側ではなく、その上位の glibc ライブラリとコンパイラの提供する I/O ライブラリ側で処理することが必要です。
そこで、本論ですが、PGI の Fortran では、以下のライブラリを提供しています。
http://www.softek.co.jp/SPG/Pgi/doc/pgifortref.pdf
3F ライブラリにある setvbuf3f ルーチンを参照してください。
integer function setvbuf3f(lu, type, size)
Argument Description
-------------------------------------------
integer lu The logical unit
integer type 0 - Full buffering
1 - Line buffering
2 - No buffering
integer size The size of the new buffer
このルーチンを I/O の前にセットして、I/O特性を定義します。なお、このルーチンは Linux System Call である setbuf 関数へ繋ぐための Fortran routine です。詳細は man setbuf(3) も参考にしてください。特に、 Full buffering、Line buffering、No buffering の設定により、今回のような問題に対処することになります。
-------------------------------------------------------------------------------------------
また、バッファリングされていてファイルシステムに書き込まれていない場合、CLOSE文にてファイルを閉じた場合に CLOSE文内部でバッファが確実にflushされるのでしょうか?それとも、PGIコンパイラで用意されている flush文が必須でしょうか?
-------------------------------------------------------------------------------------------
Close文での処理は、一般に、バッファの内容をフラッシュする処理も含むはずです。ただ、不安であれば、必ず、 FLUSH を行ってから close してください。
17. Intel Fortran、Compaq Fortran のような「環境変数」により、ユニット機番とファイル名を連結する方法について
PGIコンパイラにおいては、Intel Fortran、Compaq Fortran のような「環境変数」により、ユニット機番とファイル名を連結する機能はありません。
(例)setenv FORT10 test.plt ( あるいは export FORT10=test.plt)
その代わり、以下のような方法で、プログラム起動シェル上から同様な機能を実現できます。
PGI の場合、 OPEN 文においてファイル名を定義していない場合、あるいは、明示的に OPEN 文を指定しない場合は、デフォルトのファイル名は、以下のような形式となります。
fort.xxx : xxx がユニット機番名
例えば、
write(110) aaa
の場合は、fort.110 が自動的に作成されます。そこで、この機番ファイル名を予めシェルスクリプト上で、シンボリックリンクで「真のファイル名」にリンクしておくことにより、同様なことが実現できます。
--- shell script ----
ln -s test.plt fort.10
...プログラム実行のためのスクリプト本体...
rm fort.10 (実行後、必要がなければ delete する)
---- script 終了 ----
ln コマンドは、シンボリックリンクの方が良いと思われます。(ハードリンクの場合は、定義するそれぞれのファイルが存在していなければなりませんので)
18. Fedora Core 4 等においてデフォルトで SELinux (セキュアLinux) が動作しているシステムで、PGI ユーティリティの pgdbg、pgprof が起動時に Java のエラーで落ちます
PGI のデバッガ並びにプロファイラ (pgdbg, pgprof ) は、Java Runtime Environment を使用して実行されます。その際、以下のような Java のエラーメッセージでユーティリティの起動画面が立ち上がらない問題が発生することがあります。以下の例の場合は、ソケットを開こうとしてエラーになっているネットワーク接続関連のエラーです。
PGDBG 6.0-5 x86-64 (Workstation, 4 CPU)
Copyright 1989-2000, The Portland Group, Inc. All Rights Reserved.
Copyright 2000-2005, STMicroelectronics, Inc. All Rights Reserved.
jisx0208.1983-0" to type FontStruct
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.
invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.
invoke(DelegatingMethodAcces.sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at splashLoader$1.run(Unknown Source)
at java.lang.Thread.run(Thread.java:534)
Caused by: java.net.SocketException: Invalid argument or cannot assign
requested
address
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:305)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:171)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:158)
at java.net.Socket.connect(Socket.java:452)
at java.net.Socket.connect(Socket.java:402)
at java.net.Socket.<init>(Socket.java:309)
at java.net.Socket.<init>(Socket.java:124)
上記のような場合は、SELinux の機能を disable にして再起動後、再度ご確認ください。Fedra Core 4 では SELinux が標準で入っていて、有効になっていると色々と問題が起きるようです。 SELinux の確認方法や無効にする方法については、以下を参考にしてください。
なお、SELinux は、/etc/sysconfig/SELinux の SELinux=enforcing の行を SELinux=disabled
にして再起動すると無効に出来ます。
http://tempest.dcnblog.jp/blog/2005/06/fedora_core_4.html
http://tempest.dcnblog.jp/blog/2005/06/fedora_core_4se_b93a.html
http://faq.justsystem.co.jp/faq/1003/app/jsfaq.jsp?33417+0250
http://www.geocities.jp/code_air_edge/HP/fc4.html
19. RedHat Enterprise 4 上で、PGI ユーティリティの pgdbg、pgprof を起動する際にlibXp.so.6 がオープンできないと言うエラーで落ちます
PGI のデバッガ並びにプロファイラ (pgdbg, pgprof ) は、Java Runtime Environment (JRE) を使用して実行されます。以下のような libXp.so.6 に関する問題が発生した場合は、 JRE-1.5.x をシステムにインストールしてください。
PGDBG 6.0-4 x86-64 (Workstation, 4 CPU)
Copyright 1989-2000, The Portland Group, Inc. All Rights Reserved.
Copyright 2000-2005, STMicroelectronics, Inc. All Rights Reserved.
Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/pgi/linux86-64/6.0/jre/lib/i386/libawt.so:
libXp.so.6: cannot open shared object file: No such file or directory
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1586)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1503)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:834)
at sun.security.action.LoadLibraryAction.run(LoadLibraryAction.java:50)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Toolkit.loadLibraries(Toolkit.java:1437)
at java.awt.Toolkit.<clinit>(Toolkit.java:1458)
at splashLoader.main(Unknown Source)
-------------
JRE-1.5.x は、以下の URL から Linux 用のソフトウェアをダウンロードしてください。なお、ソフトウェアのインストール方法は、このページに明記されております。
http://www.java.com/ja/download/manual.jsp
新しく、JRE-1.5.x をインストールした directory をここでは仮に、/opt/java/jre_15 とした場合、PGI_JAVA 環境変数を以下のようにお使いのシェル上で定義します。これによって、pgdbg/pgprof ユーティリティは、この新しい JRE 環境を使用して起動されます。
(csh/tcsh)
setenv PGI_JAVA /opt/java/jre_15/bin/java
(sh/bash)
export PGI_JAVA=/opt/java/jre_15/bin/java
したがって従って、この環境の下で、再度、PGI ユーリティを起動してください。
(デバッガ、プロファイラ等の FAQ は、新しいページを設けました。こちらのページもご参照下さい。)
20. 開発中のプログラムが突然、segmentation fault で終了します。どこの部分で終了したか調べる方法はありますか
プログラムの実行時に、Segmentation fault と言うメッセージで異常終了することがあります。もし、プログラムの開発中に起きた現象であれば、プログラムのバグによる問題と思われますが、このメッセージだけでは場所を特定できません。このような場合の対処法を述べます。まず、その前に、Segmentation fault が生じる可能性のある原因について、いくつか列挙します。
(1) 配列のインデックスの定義を何らか理由で行っていない場合、この配列に参照する際、添字の範囲外のアクセスが生じて、カーネルが Segmentation fault によってインターラプトする場合(配列境界外のアクセス)
(2) OpenMP 等のスレッド並列実行する際に、システムのデフォルトの STACKSIZE では足りない領域が要求された場合
== > これに関しては、こちらをご参考にしてください
(3) コンパイラ自身の問題によるインターラプト
大きな理由として上記の三つがありますが、ここでは、ユーザプログラムの問題としてよく生じる、(1) についての対処法を説明します。 配列境界は、コンパイラの世界では「バウンズ(bounds)」と言い、そのチェックを行うことをバウンズ・チェックと言います。PGI コンパイラでは、この機能をランタイムで行うためのオプションが存在します。コンパイル時に、以下の -Mbounds オプションを入れてモジュールを作成してください。これを実行しますと、問題が存在するところでメッセージと共にプログラムは終了します。
(コンパイル)
$ pgfortran -Minfo -fastsse -Mbounds test.f
あるいは、
$ pgfortran -Minfo -fastsse -C test.f
配列境界外のアクセスを行った場合、以下のような形式で出力されます。問題となるソースコードのライン番号とその当該配列名、実際に実行時に使用された添字の数(subscript)
、そして、配列の何次元目に問題があったか等のメッセージが出力されます。これは、明らかなプログラムバグですので、修正してください。これで、本問題は、ほとんどのケース解決されます。
【Fortran の場合】
$ ./a.out
PGFTN-F-Subscript out of range for array a (add.f: 211)
subscript=99919, lower bound=1, upper bound=2, dimension=2
【C の場合】
PGC-F-Subscript out of range for array ST2 (test.c: 385)
subscript=2, upper bound=1, dimension=1
----------------------------------------------------------------------------------------
それでは、次に、このバウンズの問題以外で segmentation fault が生じた場合、どのような方法でその場所を特定するか説明します。最も簡単に行う方法は、PGI デバッガ pgdbg を使用することです。 pgdbg は、 X環境での GUI ベースのソース・デバッガですが、場所を特定することだけであれば、テキストベースによるコマンド・インタフェースでデバッガを実行します。以下の方法で行ってください。
デバッガで実行しますと、以下のように、問題となる箇所(ソース名とライン番号)を示して終了します。
【デバッガを使用する際のコンパイルのオプション】
$ pgfortran -g -O0 test.f
【デバッガを使用して実行する】
$ pgdbg -text ./a.out
PGDBG 6.0-8 x86-64 (Workstation, 4 CPU)
Copyright 1989-2000, The Portland Group, Inc. All Rights Reserved.
Copyright 2000-2005, STMicroelectronics, Inc. All Rights Reserved.
***Reading DWARFv2 Information.
Loaded: /home/taro/PGI/SEGFAULT/a.out
pgdbg>run < data (注) "< data" は data ファイルを標準入力からデータを渡すと言う意味です。
入力データがなければ、run だけでよい。
reloading:
/home/taro/PGI/SEGFAULT/a.out
libc.so.6 loaded by ld-linux-x86-64.so.2.
libm.so.6 loaded by ld-linux-x86-64.so.2.
Signalled SIGSEGV at 0x419ECA, function mat_add, file test.F, line 3807 <== ここが終了したポイントです
419ECA: 66 F 13 84 C1 C8 EF F4 FF movlpd %xmm0,-725048(%rcx,%rax,8)
PGDBG の GUI バージョンを使用するとSegmentation fault の場所で終了し、ソースレベルで場所の特定が可能。
21. 新リリース PGI 6.1 を /usr/pgi 配下にインストールしました。過去のバージョンの PGI 5.2、6.0 ソフトウェアも、/usr/pgi 配下に削除せず残しています。デフォルト・バージョンは PGI 6.1 の状態で、過去のバージョンを使用する方法はありますか
PGI コンパイラのソフトウェアは、デフォルトでインストールした場合、/usr/pgi ディレクトリ配下に実装されます。ソフトウェアのバージョン管理方法は、/usr/pgi 配下に以下のようなバージョン番号のサブ・ディレクトリが作成され管理されています。バージョンアップを繰り返し、過去のバージョン・ソフトウェアをシステム上に残留させた場合、例えば、5.2、6.0、6.1 と言うディレクトリが作成されています。
【32-bit コンパイラ用】 【64-bit コンパイラ用】
/usr/pgi/linux86/5.2 /usr/pgi/linux86-64/5.2 : PGI 5.2ソフトウェア
/usr/pgi/linux86/6.0 /usr/pgi/linux86-64/6.0 : PGI 6.0ソフトウェア
/usr/pgi/linux86/6.1 /usr/pgi/linux86-64/6.1 : PGI 6.1ソフトウェア(現在のデフォル)
上記のような状態で、ソフトウェアが実装されていた場合、コンパイラ・オプションの指定により、過去のコンパイラ・ソフトウェアを使用することができます。
-V{Release_number} オプションをコンパイラ・コマンドに付けることで、過去のバージョン番号のコンパイラを使用してコンパイルが可能となります。
(例) pgcc -V5.2 myprog.c
(関連情報)最新バージョンだけでなく、過去のバージョンも同時にインストールして各々動作しますか (Linuxの場合)
22. PGI 6.1 の PGDBG/PGPROF を使用する際、Java Runtime Environment が1.5.0_04 以上を必要とされると言うメッセージが出ます
PGI のデバッガ並びにプロファイラ (pgdbg, pgprof ) は、Java Runtime Environment (JRE) を使用して実行されます。最新の
Linux distribution を使用していない場合、JRE が古い場合があります。以下のようなメッセージが出力された場合は、 JRE-1.5.04 以上にバージョンアップしてください。
$ pgdbg
pgdbg: The PGDBG Graphical User Interface (GUI) requires java JRE 1.5.0_04
pgdbg: or higher. Using Text Interface.
PGDBG 6.1-1 x86-64 (Workstation, 4 CPU)
Copyright 1989-2000, The Portland Group, Inc. All Rights Reserved.
Copyright 2000-2005, STMicroelectronics, Inc. All Rights Reserved.
-------------
JRE-1.5.x は、以下の URL から Linux 用のソフトウェアをダウンロードしてください。なお、ソフトウェアのインストール方法は、このページに明記されております。
AMD64/EM64T の64bit のシステムでは、AMD64 用のバイナリをダウンロードしてください。なお、インストールは rpm コマンドで行われますので、JRE の環境はシステム内部に自動的に設定されます。従って、 PGI_JAVA 環境変数の設定は必要ありません。
http://www.java.com/ja/download/manual.jsp
インストール後、この環境の下で、再度、PGI ユーリティを起動してください。
(デバッガ、プロファイラ等の FAQ は、新しいページを設けました。こちらのページもご参照下さい。)
23. SUSE 10.0 (64bit) 上で PGI 6.0-8 を使用しています。コンパイルオプションに -Mipa を使用すると、リンク時にエラーが生じます。この対処法を教えてください
PGI 6.0 は、SUSE 10.0 を正式にサポートしていませんが、この OS の上で、PGI 6.0 を使用する場合も多いかと思います。SUSE 10.0 上で、コンパイルオプションに -Mipa を使用して実行モジュールを生成する際に、リンク時に以下のようなメッセージで正常終了しません。なお、PGI 6.1 ではこのような問題は生じません。
File format not recognized
この問題は、 SUSE 10.0 にバンドルされているパッケージの binutils の 2.16.91.0.2 バージョンに伴う問題です。以下に、これに対処するための方法を説明します。
① 弊社のサイトから、 suse10_patch.tar.gz (パッチファイル)をダウンロードしてください。
② ルート権限でログインし、 PGI をインストールしたトップ・ディレクトリ(/usr/pgi )に上記のパッチファイル移動してください。
③ 以下の操作を行ってください。
【パッチファイルの展開】 $ cd /usr/pgi $ ls suse10_patch.tar.gz suse10_patch.tar.gz $ tar xzvf suse10_patch.tar.gz (パッチ内容を linux86-64/6.0 配下に展開します) 【パッチでインストールされた共有ライブラリのパスをシステムに登録】 $ cd /etc $ vi ld.so.conf (ld.so.conf ファイルを開き、以下の「パス」を登録) /usr/pgi/linux86-64/6.0/patch <==== これを ld.so.conf ファイルの中に追加してください $ ldconfig (追加したパスをシステムに反映する) これで終了です
24. PGI 6.1 をインストールし、コンパイル後実行した際に、 GLIBC_2.2.5 not defined と言うエラーが生じます。この対処法を教えてください
PGI 6.1 を使用して、OpenMP 並列あるいは、自動並列化した実行モジュール (-mp or -Mconcur オプション付き) を実行すると、以下のようなメッセージでエラーが生じる場合があります。これらの実行モジュールは、システムの libpthread ライブラリを使用するものです。また、この問題が生じる Linux のバージョンは特定されていませんが、 RedHat Enterprise 3 の古いアップデート・バージョン等の Linux kerner 2.4.x のもので起こりうることが報告されております。米国 PGI 社でもこれは、既知の問題として認識されておりますが、 Linux distribution に係る問題のため、OSのアップデート等を行う他は、根本的な解決はできません。しかし、以下に述べる方法で、対処が可能です。
relocation error: /usr/pgi/linux86-64/6.1/lib/libpthread.so.0:
symbol _h_errno, version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference
ユーザ、あるいはシステムレベルで、 .bashrc or .cshrc 等のファイルで以下のような LD_ASSUME_KERNEL 環境変数の設定を行うことでこの問題への対処が可能です。
例えば、お使いの Linux のカーネルバージョンが 2.4.x であれば、以下のようにご指定ください。
export LD_ASSUME_KERNEL=2.4.1
また、お使いの Linux のカーネルバージョンが 2.2.x であれば、以下のようにご指定ください。
export LD_ASSUME_KERNEL=2.2.5
なお、Linux のカーネルバージョンの調べ方は、 cat /proc/version のコマンドで表示されます。
この問題と同じようなものが、PGI User Forum 上に記録されております。
http://www.pgroup.com/userforum/viewtopic.php?t=539
http://www.pgroup.com/userforum/viewtopic.php?t=207
別の解決法としては、各ユーザのログイン環境変数の設定(.bashrc あるいは、.cshrc) において、以下の環境変数を設定することで回避できるようです。(以下は 64bit 環境の場合)
export LD_LIBRARY_PATH=/lib64/tls:/opt/pgi/linux86-64/6.1/lib
25. PGI コンパイラで生成したオブジェクト・ファイルの PGI バージョンに依存した互換性について教えてください
(2007年4月26日)
Linux版、Windows版 に係らず、PGIコンパイラが生成するオブジェクト・ファイルの互換性 (旧バージョンで作成したオブジェクトあるいは、ライブラリをリンクして動作可能かと言うこと)
について説明します。
PGI 5.x
----------- オブジェクト互換性の境界
PGI 6.0
PGI 6.1
PGI 6.2
PGI 7.0
オブジェクトの互換性は、PGI 5.x 以前と PGI 6.x 以降では、基本的に互換性はないものと考えて下さい。これは、Linux/Windows版共通です。これがまず、基本原則です。バージョン間での互換性がないオブジェクトを使用する際は、ソースファイルからの再コンパイルをお願いいたします。
さらに、PGI 6.1以前のバージョンでコンパイルオプション -Mipa(手続き間最適化)を付加して生成したオブジェクトは、PGI 6.2以降のオブジェクトとの完全互換はありませんので、再コンパイルが必要です。
次に、Windows バージョンは、使用するシステム・ライブラリが PGI 6.1 以降変更になっております。(弊社では、PGI6.1 以降の
Windows版を正式に販売しており、それ以前のバージョンは、日本では販売しておりません)
PGI 5.x Cygwin上での32bit版のみ Linux-like environment (MINGW)
PGI 6.0 Cygwin上での32bit版のみ Linux-like environment (MINGW)
--------- Cygwin / Microsoft のシステムライブラリ使用の境界-------------
以降、ネイティブ Microsoft SDK(utility) を使用したコンパイル環境に変更
PGI 6.1 64bit版のみリリース/32bit版は欠番
PGI 6.2 64bit版、32ビット版ともにリリース
PGI 7.0 同上
26. Linux のアップデートにより GCC/Glibc のバージョンが変更された後、リンク時に GNU 関連のライブラリがリンクできず、実行モジュールの生成ができません
(2012年2月25日更新、2007年7月12日初稿)
この問題は、システムの GNU/GCC ライブラリのバージョンが、オンラインアップデートで更新されたために生じる問題です。
Red Hat Enterprise Linux のような商用ディストリビューションでは、オンライン・アップデートする機会が多いため、かなり頻繁に GNU パッケージのバージョンがアップデートされます。PGI コンパイラは、GNU/GCC のライブラリやインクルードファイルを使用しており、PGI コンパイラをインストールした時点で、システムに実装された GNU/GCC ライブラリ等のバージョン(厳密に言えば、存在するディレクトリ・パス)を PGI コンパイラの初期設定ファイル (一例:$PGI/linux86-64/{vesion}/bin/localrc) に登録しています。
(各 Linux distributions バージョンの GCC/glibc のバージョンに関してはこちらで)
もし、GNU/GCC のバージョン(たとえば、初期 GCC 3.4.4)が、オンライン・アップデートで GCC 3.4.5--> GCC 3.4.6 に順番に上がりますと、すでに登録してある PGI 初期設定ファイルの中の GCC 関係のパス名(Linux ではバージョン番号がパス名として使用している)とシステムの実態が異なる形になります。一般には、システム上でこのような GCC 等のアップデートを行うと、旧バージョン名(たとえば 3.4.5)は、実態のあるバージョンを引用できるように、シンボリック・リンクを張るのですが、Red Hat Enterprise Linux 4 等では、このリンクは最新のバージョンのものしか、シンボリックに結合していないため、頻繁にアップデートされますと、PGI 初期設定ファイルの中のGCCパス名が存在しない事態になることがあります。このような状況でコンパイルを行うと、従来可能であったことが突然コンパイルエラーとなる状況があり得ます。
% pgcc -c test.c
PGC-F-0206-Can't find include file stddef.h (/usr/include/stdio.h: 34)
PGC/x86-64 Linux/x86-64 6.1-1: compilation aborted
あるいは、
% pgf90 t.f
/usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/4.4.5/crtbegin.o: No such file: No such file or directory
PGI の初期設定ファイルの内容とシステムのアップデート状況を確認してください。
【PGI の初期設定ファイル(localrc) の場所】
PGI 32ビット環境の場所 : $PGI/linux86/{version 番号}/bin/localrc
PGI 64ビット環境の場所 : $PGI/linux86-64/{version 番号}/bin/localrc
その内容の一例(以下の例では、 GCC 3.4.4 が初期設定されています)
% cat $PGI/linux86-64/{version 番号}/bin/localrc
set LFC=-lg2c;
set LDSO=/lib64/ld-linux-x86-64.so.2;
set GCCDIR=/usr/lib/gcc/x86_64-redhat-linux/3.4.4/;
set GCCINC=/usr/lib/gcc/x86_64-redhat-linux/3.4.4/include;
set G77DIR=/usr/lib/gcc/x86_64-redhat-linux/3.4.4/;
(以下、省略)
上記の GCCDIR のディレクトリを確認してください。(3.4.4ディレクトリ、あるいはリンクはすでに消去されています)
% ls /usr/lib/gcc/x86_64-redhat-linux/
3.4.3/ 3.4.6@ 4.1.1/
こう言った形で、オンラインアップデートを行うと、旧GCCのバージョンのリンクが切れることになります。
なお、現在実装されている gcc のバージョンを調べるには、以下のコマンドを使用します。
% gcc --version
gcc (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3)
それでは、これに対する解決策を説明します。PGI の初期設定ファイル localrc を現在のシステム環境(GCCバージョン等)に沿うように更新します。もちろん、PGIを再インストールしても解決しますが、ここでは、再インストールを行わず、最も簡単な解決策を以下に示します。
ルート権限で以下の処理を行います。
セッションのシェルの言語モードを一時的に英語モードにする(必須)。
# export LANG=C
次に、PGIのインストール場所を $PGI として、以下の処理を行います。
PGI {version 番号} の初期設定ファイル (localrc) をアップデートします。{version 番号}は、6.0 とか 6.1、7.2-1
と言うバージョン番号です。
64ビット用コンパイル環境を行います。
# cd $PGI/linux86-64/{version 番号}/bin
# ./makelocalrc -x $PGI/linux86-64/{version 番号}
(例:./makelocalrc -x $PGI/linux86-64/7.*) PGI 7.0 以前のバージョン表記例
(例:./makelocalrc -x $PGI/linux86-64/7.2-*)PGI 7.1 以降のバージョン表記例
(例:./makelocalrc -x $PGI/linux86-64/10.*) PGI 10.0 以降のバージョン表記例
同様に、32ビット用コンパイル環境も行います。
# cd $PGI/linux86/{version 番号}/bin
# ./makelocalrc -x $PGI/linux86/{version 番号}
以上で、現在の gcc /glibc バージョンが反映された PGI の各バージョンの初期設定ファイルの変更が可能です。これで、問題なく、コンパイルできるはずです。なお、過去のバージョン、リビジョンを複数実装している場合は、その全てを同じように makelocalrc で処理する必要があります。この場合は、以下のようなシェルスクリプトを使い、各バージョンの localrc ファイルを変更できます。
(一例を示します) [root@photon29 linux86-64]# pwd /opt/pgi/linux86-64 (64bit環境) [root@photon29 linux86-64]# ls (以下のようなバージョンが実装されています) 10.0 10.2 10.4 10.6 10.9 11.1 11.2 11.4 11.6 11.8 12.1 2010 2012 9.0-4 10.1 10.3 10.5 10.8 11.0 11.10 11.3 11.5 11.7 11.9 12.2 2011 9.0 change-makelocalrc-64 [root@photon29 linux86-64]# cat change-makelocalrc-64 (変更するためのスクリプト例) #! /bin/bash for ver in 9.0-4 10.0 10.2 10.4 10.6 10.9 11.1 11.2 11.4 11.6 11.8 12.1 10.1 10.3 10.5 10.8 \ 11.0 11.10 11.3 11.5 11.7 11.9 12.2 do echo $ver " set" cd $ver/bin ./makelocalrc -x $PGI/linux86-64/$ver cd ../.. done [root@photon29 linux86-64]# ./change-makelocalrc-64 (スクリプトの実行) ... 過去のバージョンでは、以下に述べるエラーメッセージが出る場合があるが、これは無視する... 以上で 64ビット環境の localrc ファイルは全て変更されるはずです。 次に 32bit環境も行う。 [root@photon29 linux86-64]# cd ../linux86 [root@photon29 linux86]# pwd (32bit環境) /usr/pgi/linux86 [root@photon29 linux86]# ls 10.0 10.2 10.4 10.6 10.9 11.1 11.2 11.4 11.6 11.8 12.1 2010 2012 9.0-4 10.1 10.3 10.5 10.8 11.0 11.10 11.3 11.5 11.7 11.9 12.2 2011 9.0 change-makelocalrc-32 [root@photon29 linux86]# cat change-makelocalrc-32 #! /bin/bash for ver in 9.0-4 10.0 10.2 10.4 10.6 10.9 11.1 11.2 11.4 11.6 11.8 12.1 10.1 10.3 10.5 10.8 \ 11.0 11.10 11.3 11.5 11.7 11.9 12.2 do echo $ver " set" cd $ver/bin ./makelocalrc -x $PGI/linux86/$ver cd ../.. done [root@photon29 linux86-64]# ./change-makelocalrc-32 (スクリプトの実行)
【過去のバージョンの既知の問題】
(バージョン番号が、 7.0以前の場合の指定例)
$ ./makelocalrc -x $PGI/linux86-64/7.0
cp: cannot stat `/usr/pgi-7.0/linux86-64/7.0/lib/libpgbind_real.a': No
such file or directory
cp: cannot stat `/usr/pgi-7.0/linux86-64/7.0/libso/libpgbind_real.a': No
such file or directory
cp: cannot stat `/usr/pgi-7.0/linux86-64/7.0/libso/libpgbind_real.so':
No such file or directory
localrc has not changed
(バージョン番号が、 7.1以降の場合の指定例、パッチリビジョン 7.2-* まで指定する)
$ ./makelocalrc -x /opt/pgi/linux86-64/7.2-2
cp: cannot stat `/opt/pgi/linux86-64/7.2-2/lib/libpgbind_real.a': No such
file or directory
cp: cannot stat `/opt/pgi/linux86-64/7.2-2/libso/libpgbind_real.a': No
such file or directory
cp: cannot stat `/opt/pgi/linux86-64/7.2-2/libso/libpgbind_real.so': No
such file or directory
localrc has not changed
過去のバージョンでは既知の問題があり、上記のエラーメッセージは「無視」して結構です。また、”localrc has not changed”と言うメッセージも「無視」してください。実際には、再設定されて変更されています。(再度、localrcの内容を確認してみてください)
念のため、 ls -lt で、 localrc と locarc.bak ファイルの二つの内容 と更新日付を確認して見てください。適格なGCCバージョンがセットされていれば、問題なく動作します。
27. PGI 7.1 からバンドルされた MPICHライブラリや、MPIプログラム用のツールの使用方法を教えてください
PGI Workstation/Server ライセンス製品と PGI CDKライセンス製品で使用可能な MPICH ライブラリの利用方法に関しては、別のページを設けましたので、こちらをご覧ください。
28. PGI Workstation ライセンスで生成した実行モジュールの使用可能な並列スレッド数の上限値は、バージョンによって変更されていますか
PGI Workstation ライセンスで生成した実行モジュールの「使用可能な並列スレッド数の上限値」は、各バージョンにより異なります。
過去のバージョンを使用している場合は、その上限値で制約されます。一般的には、「使用可能な並列スレッド数の上限値」は、環境変数 OMP_NUM_THREADS
あるいはNCPUS で定義する数字となります。
PGI 6.1 以前 : 4 まで
PGI 6.2/7.0 : 8CPUソケットまでのコア総数が上限(インテル・プロセッサシステムの場合は、
異なる場合があります)
PGI 7.1 以降 : 最大 256 (正確には、デフォルトで内部的な最大値は 64 スレッドまでという制約が
あります)
もし、64 threads 以上の並列実行をしたい場合は、内部的なデフォルト値64を変更するための環境変数として、NCPUS_MAX がありますので、この値を任意に設定します。その後に、実際に実行時に使用するスレッド数を OMP_NUM_THREADS で指定して下さい。
(一例)
$ export NCPUS_MAX=256
$ export OMP_NUM_THREADS=256
$ ./a.out
PGI 7.1以降は、この制約自体を撤廃しましたので、論理的には、現在販売されているマシンの物理的な上限コア数で並列実行できます。これに関しては、以下に説明しています。
http://www.softek.co.jp/SPG/Pgi/product_matrix70.html
http://www.softek.co.jp/SPG/Pgi/product.html#licenses
従って、使用するコンパイラのバージョンによって、生成された実行モジュールの使用可能な並列スレッド数の上限値は変化するということを予めご了承ください。
29. PGI C++コンパイラ(pgCC or pgcpp)環境において、C言語の ISO/IEC C99 規約で定義されている関数を組み込む方法を教えて下さい
例えば、nan() 等の C 言語の ISO/IEC C99 規格に準拠した関数を PGI C++コンパイラで使用する場合は、以下に述べる方法で、明示的に、関数の組込を指定しなければなりません。
以下のテストプログラムには、nan() 関数を使用しています。このプログラムファイルを test.cpp とします。
#include <iostream> #include <sstream> #include <cmath> int main() { std::ostringstream ost1; double x = nan(""); ost1 << -x; std::cout << ost1.str() << std::endl; return 0; } ------------------------------------------------- これをコンパイルすると、nan() 関数が見つからないと言うエラーとなる $ pgCC test.cpp "nan.cpp", line 7: error: identifier "nan" is undefined double x = nan(""); 1 error detected in the compilation of "nan.cpp".
以下のどちらかの方法で、 nan() 関数を明示的に include します。
① コンパイル・オプション pgCC -D_ISOC99_SOURCE test.cpp
② ソース上で定義(以下を追加) extern "C" double nan (const char *);
#include <iostream> #include <sstream> #include <cmath> int main() { std::ostringstream ost1; double x = nan(""); ost1 << -x; std::cout << ost1.str() << std::endl; return 0; } ------------------------------------------------- $ pgCC -D_ISOC99_SOURCE test.cpp OK
30. PGI 11.0 (PGI 2011)以降の PGFORTRAN コンパイラで実行モジュールを作成し実行すると、実行終了時に、ieee_inexact is signaling と言う警告メッセージが出ます。この意味とこのメッセージを抑止する方法を教えて下さい
PGI 11.0 から正式に Fortran 2003 完全準拠となりました。この Fortran 2003 標準規約では、プログラムの浮動小数点演算実行時に、プロセッサ演算機構の中で一般的な IEEE の例外シグナルが発生した場合、そのメッセージをプログラム実行終了時に、出力するように求められています。今回の問題の「ieee_inexact シグナル」とは、プロセッサの浮動小数点演算において「不正確」、すなわち、丸められた有効な演算結果が、無限精度の結果と異なるような事象が少なくとも1度以上生じた場合のプロセッサ・ハードウェアによるシグナルです。これがプログラムにおいて受け入れられるものかどうかは、そのプログラムの実行時の特性によって異なります。これに関しては、ユーザの責任で判断することになります。一般に、こうした IEEE 例外事項が発生した場合は、「デフォルトの動作」により処理は続行しており、今までは気がついていない場合も多々あるのかもしれません。なお、これは、PGIコンパイラの生成コードが出すシグナルではなく、プロセッサ自体の例外処理シグナルを出力していることにご注意下さい。また、「致命的なエラーメッセージ」ではなく、「情報レベル」のメッセージであると言うこともご理解下さい。
このメッセージの抑止方法は、プログラムの STOP 文を削除することです。 STOP 文が存在する時にのみ、Fortran 2003 の例外シグナルメッセージを出力します。あるいは、環境変数 NO_STOP_MESSAGE を設定することでも抑止されます。NO_STOP_MESSAGE に対する値の設定は「任意」です。例えば、 export NO_STOP_MESSAGE=y と言う設定で構いません。
31. Sandybridge プロセッサを搭載した OS X 10.7 (Lion) 上で PGI 11.x (PGI 2011) を使用してコンパイルすると、no such instruction: `vzeroupper' と言うエラーメッセージが出ます
2011年から発売されている Mac には、インテル(R) の Sandybridge プロセッサが搭載されています。2011 年時点で、この新しいプロセッサに対応した
OS X 10.7 (Lion)上で、PGI 11.x を使用してコンパイルを行うと以下のようなアセンブラレベルのエラーが出ます。この原因は、OS X の開発環境 Xcode 4.2 (2011/12現在)に含まれる GNU 環境のアセンブラ(as) が、 Sandybridge プロセッサ対応となっていないためです。PGI コンパイラは、実行時、搭載プロセッサの種別を識別し、その CPU ターゲットに沿った最適化を行います。この環境では、PGI は、Sandybridge 用の新しいプロセッサ命令(AVX)を含む中間アセンブリコードを生成しているため、Xcode/GNU のアセンブラがこのコードを認識できなかったことにより、こうしたエラーが出現します。今後の OS X の Xcode のバージョンで対応できるものと思います。この問題は、PGI 12.10 まで更新(修正)されていません。
(追記)PGI 13.2 (2013年2月リリース)以上、かつ Xcode 4.5.2 以上において、この問題を解決し、こうしたエラーは生じません。
Macbookpro$ pgf90 test.f90 test.f90:74:no such instruction: `vzeroupper' test.f90:83:no such instruction: `vzeroupper' test.f90:90:no such instruction: `vzeroupper' test.f90:97:no such instruction: `vzeroupper' test.f90:101:no such instruction: `vzeroupper' test.f90:107:no such instruction: `vzeroupper' test.f90:234:no such instruction: `vzeroupper'
この問題を回避するためには、コンパイル時に以下のオプション -tp を追加して下さい。プロセッサのターゲットを nahalem にして、実行バイナリを作成します。
Macbookpro$ pgfortran/pgcc/pgCC -tp nehalem-64 {ソースファイル名}
32. PGI CDK 12.2 以降で、CDK ソフトウェアにバンドルされた MPICH2 の mpiexec を実行できません。エラーメッセージは、mpiexec: error while loading shared libraries: libpgmp.so: cannot open shared object file: No such file or directory と言うものです
PGI CDK 12.2 の mpich2 関連のコマンド(バイナリ)内に含まれている Library PATH (-rpath) が 過去の 12.1 バージョン($PGI/linux86-64/12.1/libso)を探すようにハード・コーディングされているために、こうした問題が生じます。この問題の回避は、各ユーザの .bashrc 等に以下の2行の LD_LIBRARY_PATH を設定して下さい。以下のパス名の太字の 12.2 の部分は、インストールした CDK のリビジョン名です。これは適宜、実装リビジョン番号名に変更して下さい。
(linux86-64 の場合) export LD_LIBRARY_PATH=$PGI/linux86-64/12.2/mpi2/mpich/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=$PGI/linux86-64/12.2/libso:$PGI/linux86-64/12.2/lib:$LD_LIBRARY_PATH
33. PGI 2016 (16.3)以降、Windows版は C++ コンパイラの提供が終了しました。旧バージョン PGI 15.10 の C++ コンパイラを使用できますか? その方法を教えて下さい。
PGI 2016 以降の Windows 版では C++ コンパイラを使用することができません。しかし、PGI 15.10 以前のバージョンにバンドルされた C++ コンパイラは、PGI 2016(Fortran/Cライセンス)以降用に取得した license.dat 環境下でも使用することができます(同じライセンスファイル環境で古いバージョンを使用することができます)。なお、PGI 16.1 以降 PGPROF ユーティリティ機能が全く新しくなったため、PGI 15.10 以前の PGPROF バージョンを利用したい場合も PGI 15.10(終息バージョン)を Windows 上にインストールして下さい。但し、C++ コンパイラに関しては以下の注意事項があります。
現在、PGI 16.x 以降をすでにインストールしてある環境であることを前提に説明します。新たに、PGI Workstation 15.10 をインストールして下さい。インストール方法は、弊社の「お客様専用サポートページ」内にあるインストールの手引きをご参照ください。なお、以下の注意点を守っていただければ、ダウンロードした exe ファイルを実行するだけで簡単に実装できます。
PGI 15.10 のインストールが終了しますと、これ以降、PGI 15.10 用の PGI コマンドプロンプト端末を開くとその中で PGI C++ (旧 pgcpp コマンドを使用すること。pgc++ コマンドではありません)を使用することが出来ます。なお、デスクトップ上に PGI 15.10 用のアイコンを作成しなかった場合の、PGI 15.10 コマンドプロンプト端末の開き方を説明します。