ホーム » ソフトウェア » PGIコンパイラ

PGIコンパイラ利用法

最終更新日:2019年1月15日

PGIコンパイラはPGI社の提供するC/C++, Fortran向けのコンパイラです。 ここでは、主にプログラミング言語 Fortran, C, C++の翻訳・実行方法とバッチ処理方法について解説します。
PGIコンパイラはCUDA FortranOpenACC向けのコンパイラとしても利用可能です。 これらについては個別のページの説明をご確認ください。


利用環境

システム・バージョン・利用範囲

  • サブシステムA
  • バージョン 九州大学構成員 学術研究機関構成員 民間利用の方
    17.7
  • サブシステムB
  • バージョン 九州大学構成員 学術研究機関構成員 民間利用の方
    17.7
  • 基本フロントエンド
  • バージョン 九州大学構成員 学術研究機関構成員 民間利用の方
    17.7
  • 大容量フロントエンド
  • バージョン 九州大学構成員 学術研究機関構成員 民間利用の方
    17.7

ITOシステムにインストールされているPGIコンパイラ(CUDA Fortran, OpenACCを含む)は、 ライセンスの都合上、九州大学の構成員でなければ利用できません。 また、このコンパイラの最新版は ITOでは利用できません。
九州大学の構成員以外の方や、より新しいバージョンの PGIコンパイラを試したい方は、 Community Edition の利用をご検討ください。


利用コマンド

プログラム言語の翻訳・リンクのための書式とコマンドの一覧は以下の通りです。

コマンド [option] file [...]
言語処理系 コマンド OpenMP*
非MPI並列 Fortran pgfortran -mp
C pgcc
C++ pgc++
MPI並列 Fortran mpifort
C mpicc
C++ mpic++

* OpenMPオプションはデフォルトでは無効です。


利用方法

環境設定(moduleコマンド)

moduleコマンドによる環境設定はコンパイル時と実行時の両方で行う必要があります。

$ module load pgi/17.7

PGIに内包された Open MPIを用いる場合は、以下も実行してください。

$ module load pgi/17.7_openmpi

C/C++

C/C++コンパイラは pgcc / pgc++コマンドを利用します。 PGIに内包された Open MPIを使用する場合はmpicc / mpic++を利用します。 (以下のプログラム例では pgccおよびmpiccのみを記載しますのでC++を使う場合はpgc++およびmpic++に読み替えてください。)

例1)逐次プログラム

$ pgcc -fast -tp=haswell sample.c

例2)ノード内スレッド並列(OpenMP)プログラム

$ pgcc -fast -mp -tp=haswell sample.c

例3)MPI並列(フラットMPI)プログラム

$ mpicc -fast -tp=haswell sample.c

例4)ハイブリッド並列(OpenMP+MPI)プログラム

$ mpicc -fast -mp -tp=haswell sample.c

Fortran

Fortranコンパイラは pgfortran コマンドを利用します。 MPIライブラリを使用する場合はmpifort コマンドを利用します。 pgf77/pgf90やmpif77/mpif90など、Fortranのバージョンに合わせたコマンドも存在しますが、 特別な事情のない限りpgfortranとmpifortさえ使用すれば十分です。

例1)逐次プログラム

$ pgfortran -fast -tp=haswell sample.f90

例2)ノード内スレッド並列(OpenMP)プログラム

$ pgfortan -fast -mp -tp=haswell sample.f90

例3)MPI並列(フラットMPI)プログラム

$ mpifort -fast -tp=haswell sample.f90

例4)ハイブリッド並列(OpenMP+MPI)プログラム

$ mpifort -fast -mp -tp=haswell sample.f90

主な翻訳時オプション

翻訳時オプション 説明
-c オブジェクトファイルまで生成
-o exe_file 実行可能ファイル名/オブジェクトファイル名をexe_fileに変更
実行可能ファイル名を省略した場合にはa.out
-O[0, 1, 2, 3, 4] 最適化レベルを指定。-Oの後の数字を省略した場合は-O1に近いレベルとなる。
-fast 高速化のための最適化オプションを誘導(最適化での推奨オプション)
-mp OpenMPディレクティブを有効化。
-I directory インクルードファイル、モジュールファイルを検索するディレクトリを指定
-Mfixed (Fortranのみ) ソースコードが固定形式で記述されていることを指定
-Mfree (Fortranのみ) ソースコードが自由形式で記述されていることを指定
-cpp または -Mpreprocess プリプロセス処理を行う
-Minfo=options optionsで指定した種類の最適化情報を出力する。allで全て、mpでOpenMPに関する情報のみを出力など。
-tp=architecture architectureで指定したアーキテクチャ(およびそれ以上)のCPU向けのコード生成を行う。ITOシステムではhaswellを指定する。
(Community Editionの PGIコンパイラ、バージョン 18.1以降を利用する場合は、skylakeを指定する。))
-c99 および -c11 (Cのみ) C99規格およびC11規格に基づいたコンパイル処理を行う
-help コンパイルオプションの一覧を表示
-V コンパイラのバージョン情報を出力

推奨オプション以外の最適化機能は、プログラムデータの特性によって効果がある場合と、そうでない場合があり、実際に動作させて検証する必要があります。 推奨オプションを指定すると、関連して複数の最適化オプションが誘導されます。

Fortran, C/C++の標準的なオプションとして、-fastを推奨します。


数値計算ライブラリ

PGIコンパイラから利用できる数値演算ライブラリに LAPACK, BLAS, FFTがあります。 さらにMPIライブラリからはScaLAPACKも利用できます。 コンパイル時にそれぞれ-llapack, -lblas, -fft, -Mscalapackオプションを付けてください。


バッチ処理

ITOのサブシステム A/BでPGIコンパイラで作成した実行可能ファイル(モジュール)を実行するためには、 「バッチ処理」と呼ばれる手続きにより計算サーバーに処理の依頼をする必要があります。

バッチ処理の詳細は バッチ処理を参照してください。

以下にPGIコンパイラで翻訳した実行可能ファイルをバッチ処理により処理するスクリプトの例を示します。


例1)逐次プログラム

  • 仮想ノード数
  • :1ノード(1プロセス)
  • 仮想ノード当たりのコア数(スレッド数)
  • :1コア(1スレッド)(リソースグループの利用可能コア数を指定)
  • 最大経過時間
  • :10分
  • 標準エラー出力と標準出力を同じファイルに保存
  • :あり
  • ジョブリソースグループ(キュー)
  • :ito-single
    #!/bin/bash
    #PJM -L "rscunit=ito-a"
    #PJM -L "rscgrp=ito-single"
    #PJM -L "vnode=1"
    #PJM -L "vnode-core=1"
    #PJM -L "elapse=10:00"
    #PJM -j
    #PJM -X
    
    module load pgi/17.7
    ./a.out
    
    
    サブシステム名(ito-a)の指定
    リソースグループ(ito-single)の指定
    仮想ノード数を指定
    仮想ノードあたりのコア数を指定
    最大経過時間の指定
    標準エラー出力を標準出力に重ねる
    ジョブ投入時の環境変数をジョブ実行環境に継承
    
    環境設定
    ジョブの実行
    


    例2)ノード内スレッド並列(OpenMP)プログラム

  • 仮想ノード数
  • :1ノード(1プロセス)
  • 仮想ノード当たりのコア数(スレッド数)
  • :36コア(36スレッド)(リソースグループの利用可能コア数を指定)
  • 最大経過時間
  • :10分
  • 標準エラー出力と標準出力を同じファイルに保存
  • :あり
  • ジョブリソースグループ(キュー)
  • :ito-ss-dbg
    #!/bin/bash
    #PJM -L "rscunit=ito-a" 
    #PJM -L "rscgrp=ito-ss-dbg"
    #PJM -L "vnode=1"
    #PJM -L "vnode-core=36"
    #PJM -L "elapse=10:00"
    #PJM -j
    #PJM -X
    
    module load pgi/17.7
    export OMP_NUM_THREADS=36
    ./a.out
    
    
    サブシステム名(ito-a)の指定
    リソースグループ(ito-ss-dbg)の指定
    仮想ノード数を指定
    仮想ノードあたりのコア数を指定(リソースグループの利用可能コア数を指定)
    最大経過時間の指定
    標準エラー出力を標準出力に重ねる
    ジョブ投入時の環境変数をジョブ実行環境に継承
    
    環境設定
    スレッド数の指定
    ジョブの実行
    

    例3)フラットMPI並列プログラム

  • プロセス数
  • :144プロセス
  • 物理ノード数(仮想ノード数)
  • :4ノード
  • プロセスの割り当て
  • :1ノードあたり36プロセス
  • 最大経過時間
  • :10分
  • 標準エラー出力と標準出力を同じファイルに保存
  • :あり
  • ジョブリソースグループ(キュー)
  • :ito-s-dbg
    #!/bin/bash
    #PJM -L "rscunit=ito-a" 
    #PJM -L "rscgrp=ito-s-dbg"
    #PJM -L "vnode=4"
    #PJM -L "vnode-core=36"
    #PJM -L "elapse=10:00"
    #PJM -j
    #PJM -X
    
    module load pgi/17.7_openmpi
    mpirun -n 144 -map-by ppr:36:node --bind-to none -mca plm_rsh_agent /bin/pjrsh -machinefile ${PJM_O_NODEINF} ./a.out
    
    
    サブシステム(ito-a)の指定
    リソースグループ(ito-s-dbg)の指定
    仮想ノード数(物理ノード数)を指定
    仮想ノードあたりのコア数を指定(= 物理ノード当たりのコア数を指定)
    最大経過時間の指定
    標準エラー出力を標準出力に重ねる
    ジョブ投入時の環境変数をジョブ実行環境に継承
    
    環境設定
    MPIプログラムを起動
    


    例4)ハイブリッド並列化プログラム

  • プロセス数
  • :16プロセス
  • 1プロセスあたりのスレッド数
  • :9スレッド
  • 物理ノード数(仮想ノード数)
  • :4ノード
  • プロセスの割り当て
  • :1ノードあたり4プロセス
  • 最大経過時間
  • :10分
  • 標準エラー出力と標準出力を同じファイルに保存
  • :あり
  • ジョブリソースグループ(キュー)
  • :ito-s-dbg
    #!/bin/bash
    #PJM -L "rscunit=ito-a" 
    #PJM -L "rscgrp=ito-s-dbg"
    #PJM -L "vnode=4"
    #PJM -L "vnode-core=36"
    #PJM -L "elapse=10:00"
    #PJM -j
    #PJM -X
    
    module load pgi/17.7_openmpi
    export OMP_NUM_THREADS=9
    mpirun -n 16 -map-by ppr:4:node --bind-to none -mca plm_rsh_agent /bin/pjrsh -machinefile ${PJM_O_NODEINF} ./a.out
    
    
    サブシステム(ito-a)の指定
    リソースグループ(ito-s-dbg)の指定
    仮想ノード数(物理ノード数)を指定
    仮想ノードあたりのコア数を指定
    最大経過時間の指定
    標準エラー出力を標準出力に重ねる
    ジョブ投入時の環境変数をジョブ実行環境に継承
    
    環境設定
    OpenMPスレッド並列数を設定
    MPIプログラムを起動
    
    Open MPIの詳細な利用方法は以下を確認してください。
    Open MPI Documentation

    Open MPIによるプロセスのノードへの割り当て指定

    以下は、Open MPIでプロセスをノードに割り当てる方針を指定する例です。 -display-devel-map は、割当の結果を表示するオプションです

    # 1ソケットに1プロセス、合計2プロセスの例(1ノードで2プロセス並列実行をする想定)
    mpirun -n 2 -display-devel-map -map-by ppr:1:socket --mca plm_rsh_agent /bin/pjrsh -machinefile ${PJM_O_NODEINF} ./a.out
    # 1ノードに1プロセス、合計2プロセスの例(2ノードで2プロセス並列実行をする想定)
    mpirun -n 2 -display-devel-map -map-by ppr:1:node --mca plm_rsh_agent /bin/pjrsh -machinefile ${PJM_O_NODEINF} ./a.out
    # 1ノードに2プロセス、合計4プロセスの例(2ノードで4プロセス並列実行をする想定)
    mpirun -n 4 -display-devel-map -map-by ppr:1:socket --mca plm_rsh_agent /bin/pjrsh -machinefile ${PJM_O_NODEINF} ./a.out
    mpirun -n 4 -display-devel-map -map-by ppr:2:node --mca plm_rsh_agent /bin/pjrsh -machinefile ${PJM_O_NODEINF} ./a.out
    # 上記の2つのmpirunは厳密には意味が異なりますが、
    # どちらも1つ目のノードの2ソケットに1プロセスずつ割り当てた後に2つ目のノードの2ソケットに1プロセスずつ割り当てられます。
    # ノードを交互に使いたい(1つ目のノードにプロセス0と2、2つ目のノードにプロセス1と3、としたい)場合は
    # --rank-by nodeというオプションを追加してください
    

    参考資料