NVIDIA HPCコンパイラを手早く使ってみたいというユーザのために、性能を向上させるためのオプションから説明していきます。

その後、様々な目的のために使用されるコンパイラ・オプションを順番に説明していくこととします。

2022年8月

システム情報を知るための便利なコマンド

コンパイラがインストールされているシステム(使用するシステム)のCPU(「ターゲットCPU」という)の仕様と特性を調べるコマンドnvcpuidを実行してみてください。

並列実行させる際の物理コア数やAVXの種類や最適化のためのターゲットCPUがskylakeであることが分かります。
特に、OpenMPで並列スレッド数を指定する際に、CPUコア数が分からないような場合、このコマンドで実際のコア数を知ることができます。

$ nvcpuid
vendor id       : GenuineIntel
model name      : Intel(R) Xeon(R) W-2123 CPU @ 3.60GHz
cpu family      : 6
model           : 85
name            : Skylake Xeon
stepping        : 4
cores           : 12334
sockets         : 1
processors      : 8  (実際の物理コア数は4、Hyper threadingの2を乗じた数)
threads         : 2 (Hyper threading による論理スレッド数)
clflush size    : 8
L1i cache size  : 32KB
L1d cache size  : 32KB
L2 cache size   : 1024KB
L3 cache size   : 8448KB
flags           : acpi aes apic avx erms avx2 avx512f avx512dq avx512cd
flags           : avx512bw avx512vl md_clear ibrs stibp l1d_flush
flags           : ia32_arch_cap ssdb cflush cmov cplds cx8 cx16 de dtes f16c
flags           : ferr fma fpu fxsr ht lm lzcnt mca mce mmx monitor movbe msr
flags           : mtrr nx osxsave pae 1GBpages pat pdcm pge popcnt prefetchw
flags           : pse pseg36 rdtscp selfsnoop speedstep sep sse sse2 sse3
flags           : ssse3 sse4.1 sse4.2 syscall tm tm2 tsc vme xsave xtpr
base freq       : 3600MHz
max  freq       : 3900MHz
bus  freq       : 100MHz
default target  : -tp skylake (target cpuは、skylake)

一方、システムに搭載されているGPUアクセラレータの仕様を調べる場合は、以前に説明したとおり、以下のコマンドでGPUの仕様が表示されます。

特に、重要なのは搭載されているGPUの世代、Compute Capability(CC)です。
以下の場合はCC86(CC8.6)のGPUであることを示しています。

$ nvaccelinfo
(前略)
Default Target:                cc86

コンパイラのコマンドライン構文

nvfortranコマンドなど、コンパイラを起動するために使用されるコマンドは、コンパイラ・ドライバと呼ばれますが、以下の記述では、単に(コンパイラ)コマンドと表記しています。

コンパイラ・ドライバには、以下の構文に示すようなコマンドライン・オプションが指定され、コンパイル・プロセスのさまざまな側面を制御します。

コマンドライン構文

例として nvfortran を使用したコンパイラのコマンドライン構文は次のとおりです。

nvfortran [options] filename

[options]
一つまたは複数のコマンドライン・オプションです。ハイフン (-⁠) で始まる文字(列)をオプションとして認識します。

filename
コンパイルシステムによって処理されるソース ファイル、前処理されたソース ファイル、アセンブリ言語ファイル、オブジェクト ファイル、またはライブラリの名前です。複数のファイル名を指定できます。

コマンドライン・オプション指定の例

以下は、nvc++を使用して複数のオプションを指定した場合の一例です。太字で表している文字がオプションです。

nvc++ -fast -Mvect=simd:512 -O3 -Mlist test.cpp sub.o -o test.exe

オプションの表記法としては、-fastや-O3のようなハイフン(-)以降、単独の文字(列)の場合だけでなく、等号(=)を連結してサブオプションも記述するタイプもあります。

オプションの意味を知りたければ

入力ファイルを指定せずに、対象のオプションと組み合わせて -⁠helpを指定して NVIDIA HPCコンパイラ を呼び出すことにより、任意のコマンドライン・オプションの仕様を表示できます。

$ nvc -Mlist -Mvect:256 -help
Reading rcfile /opt/nvidia/hpc_sdk/Linux_x86_64/22.5/compilers/bin/.nvcrc
-M[no]list          Generate a listing file
-M[no]vect[=[no]altcode|[no]assoc|cachesize:<c>|[no]fuse|[no]gather|[no]idiom|levels:<n> |nocond|[no]partial|prefetch|[no]short|[no]simd[:{128|256}]|[no]simdresidual|[no]sizelimit[:n]|[no]sse|[no]tile]
                    Control automatic vector pipelining
    [no]altcode     Generate appropriate alternative code for vectorized loops
    [no]assoc       Allow [disallow] reassociation
    cachesize:<c>   Optimize for cache size c
    [no]fuse        Enable [disable] loop fusion
    [no]gather      Enable [disable] vectorization of indirect array references
    [no]idiom       Enable [disable] idiom recognition
    levels:<n>      Maximum nest level of loops to optimize
    nocond          Disable vectorization of loops with conditionals
    [no]partial     Enable [disable] partial loop vectorization via inner loop distribution
    prefetch        Generate prefetch instructions
    [no]short       Enable [disable] short vector operations
    [no]simd[:{128|256}]
                    Generate [don't generate] SIMD instructions
     128            Use 128-bit SIMD instructions
     256            Use 256-bit SIMD instructions
     512            Use 512-bit SIMD instructions
    [no]simdresidual
                    Enable [disable] vectorization of the residual loop of a vectorized loop
    [no]sizelimit[:n]
                    Limit size of vectorized loops
    [no]sse         The [no]sse option is deprecated, use [no]simd instead.
    [no]tile        Enable [disable] loop tiling

-help オプションに対して-helpを行うと、オプション・グループに関する情報を返すことができ、⁠help自体の完全な機能を確認できます。

以下のようなオプション指定により、コンパイラのオプション・グループ名を表示できます。

$ nvc -help -help
Reading rcfile /opt/nvidia/hpc_sdk/Linux_x86_64/22.5/compilers/bin/.nvcrc
-help[=groups|asm|debug|language|linker|opt|other|overall|phase|prepro|suffix|switch|target| variable]
                    Show compiler switches

例えば、debugグループに係るオプションを表示させたい場合は、-help=debugグループを指定します。

debuggingに関するコマンドライン・オプションが表示されます。

$ nvc -help=debug
Reading rcfile /opt/nvidia/hpc_sdk/Linux_x86_64/22.5/compilers/bin/.nvcrc

Debugging switches:
-g                  Generate information for debugger
-gopt               Generate information for debugger without disabling optimizations
-M[no]bounds        Generate code to check array bounds
-Mchkstk            Check for sufficient stack space upon subprogram entry
-Mcoff              Generate COFF format object
-Mdwarf3            Generate DWARF3 debug information with -g
-Melf               Generate ELF format object
-Memit-dwarf-inlined
                    Enable generation of DWARF for inlined functions
-Mnodwarf           Do not add DWARF debug information
-[no]traceback      Add debug information for runtime traceback

最適化オプションとして、-fastを覚えておこう

ここでは、マルチコアCPUのパフォーマンスを向上させるのに有効ないくつかのコマンドライン・オプションの概要について説明します。

NVIDIA HPC Compilers は、ユーザが各最適化フェーズを細かく制御できるように、幅広いオプションを実装しています。コードの最適化に関しては、-fast オプションを使用するのが最も手っ取り早い方法です。これらのオプションは、一般的に最適なフラグのセットを作成します。64ビットターゲットでは、ベクトルストリーミングSIMD命令を使用できるようにするための最適化オプションを組み込んでいます。
SIMD命令によるベクトル化、キャッシュのアライメント、flush-to-zeroモードが有効となります。

※注: -⁠fastオプション の内容は、ホストによって異なります。
なお、当該オプションは、コンパイルとリンクの両方のコマンドラインで使用する必要があります。

最適化を施してコンパイル&リンクしたい場合は、以下のようなオプションを設定してください。
-Minfoオプションは、コンパイル時の最適化メッセージを出力するものであり、最適化の状況が分かるため、常に付けてコンパイルすることをお勧めします。

$ nvfortran -fast -Minfo test.f90 (Fortranコンパイラ)
$ nvc -fast -Minfo test.c     (Cコンパイラ)
$ nvc++ -fast -Minfo test.cpp   (C++コンパイラ)

次の表に、具体的に-fastオプションが包括しているオプションの内容を示しました。

オプション機能
-02コード最適化レベル2を指定します。
-Munroll=c:1 ループを展開し、各反復の間に元のループの複数のインスタンスを実行します。
-Mnoframeスタックフレームをセットアップするためのコードを生成しない。注:このオプションでは、スタックトレースは機能しません。
-Mlreループ・キャリードの冗長性排除を有効にする。
-Mpre部分的な冗長性の排除を可能にする

さらに、最近のほとんどのCPUでは、-fastには以下の表に示すようなオプションも含まれています。

オプション機能
-Mvect=simdPacked SIMD 命令を生成します。
-Mcache_align長いオブジェクトをキャッシュライン境界で整列させる。
-Mflushzflush-to-zero モードをセットします。
-M[no]vect自動ベクターパイプラインを制御します。

さらなるグローバルな最適化オプション

-fastオプションは最高のパフォーマンスを得るために設計されていますが、一つのルーチン内に留まる最適化であるため、ローカルな最適化(最適化境界)に限定されます。

ソースコードの性質や書き方にもよりますが、コンパイラは与えられたルーチンで使用されているグローバルなコンテキストを知ることで、さらなる最適化ができることがよくあります。例えば、ルーチンの実際のパラメータが取り得る値の範囲を決定すれば、ループをベクトル化することができます。

同様に、呼び出しの静的な状態を決定できれば、どのルーチンをインライン化するのが有益かを決定でき最適化を施すことができます。

これらのタイプのグローバル最適化は、NVIDIA HPCコンパイラの Interprocedural Analysis (IPA) の制御下にあります。

オプション -Mipa は、Interprocedural Analysis を有効にします。
-Mipa=fastは、グローバル最適化で最高の性能を得るために推奨されるオプションです。また、サブオプションのinlineを追加すると、プログラム・ファイル間で自動的にグローバルインラインを有効にすることができます。

さらなるグローバルな最適化を行うには、-Mipa=fast,inlineの使用を検討されるとよいでしょう。
プロシージャ間解析とグローバル最適化のためのこのオプションは、パフォーマンスを向上させることができます。

$ nvfortran -fast -Mipa=fast,inline -Minfo test.f90 sub.f90 (Fortranコンパイラ)
$ nvc -fast -Mipa=fast,inline -Minfo test.c sub.c       (Cコンパイラ)
$ nvc++ -fast -Mipa=fast,inline -Minfo test.cpp sub.cpp    (C++コンパイラ)

よく使用されるコンパイル・オプション

総合的な性能を高めるオプションに加えて、多くのユーザが使い始めの頃に便利だと感じるオプションが多数あります。次表では、これらのオプションに関して簡単に説明しています。

オプション機能
-⁠accOpenACC ディレクティブを使用して並列化を有効にします。デフォルトでは、コンパイラは OpenACC 領域を並列化し、NVIDIA GPU にオフロードします。使用する-⁠acc=multicoreマルチコア CPU のすべてのコアで実行するために OpenACC 領域を並列化します。
-⁠fastこのオプションは、SIMD 機能をサポートするターゲットに対して一般的に最適なフラグのセットを作成します。ベクトルストリーミング SIMD 命令、キャッシュ・アライメント、flushz を使用できるようにする最適化オプションが組み込まれています。
-⁠gオブジェクト・モジュールにシンボリック・デバッグ情報を含めるようコンパイラに指示します。コマンドラインに-Oオプションがない限り、最適化レベルをゼロに設定します。逆に、DWARF情報を生成しないようにするには、-Mnodwarfオプションを使用します。
-⁠goptオブジェクト・ファイルにシンボリック・デバッグ情報を含めるようコンパイラに指示し、-g が指定されていないときと同じ最適化されたコードを生成するようにします。
-⁠gpuコードが生成されるGPUの種類、対象となるCUDAのバージョン、その他GPUコード生成のいくつかの側面を制御します。
-⁠help利用可能なオプションの情報を提供します。
-⁠mcmodel=medium 64ビットターゲット用のmedium=modelコード生成を有効にし、プログラムのデータ容量が4GBを超える場合に有効です。
-⁠mpOpenMPディレクティブを使用した並列化を有効にします。デフォルトでは、コンパイラはマルチコアCPUのすべてのコアで実行するためにOpenMPリージョンを並列化します。NVIDIA GPUにオフロードするためにOpenMPリージョンを並列化するには、-mp=gpuを使用します。
-⁠Mconcurループの自動並列化を有効にするようコンパイラに指示します。指定された場合、コンパイラは並列化可能であると判断したループを複数のCPUコアを使用して実行するため、ループの反復はマルチスレッド実行コンテキストで最適に実行されるように分割される。
-⁠Minfo標準エラーに情報を出力するようコンパイラに指示する。
-⁠Minline関数のインライン化を可能にする。
-⁠Mipa=fast,inlineプロシージャ間の解析と最適化を可能にします。また、自動的なプロシージャのインライン化も可能です。
-⁠Mkeepasm生成されたアセンブリファイルを保持します。
-⁠Munrollループアンローラーを起動してループを展開し、各反復の間にループの複数のインスタンスを実行します。また、最適化レベルが 2 未満に設定されている場合、または -O や -g オプションが指定されていない場合、最適化レベルが 2 に設定されます。
-⁠M[no]vectコードベクタライザーを有効[無効]にします。
--⁠[no]exceptionsユーザーコードから例外処理を削除します。C++の場合、このファイル内の関数はC++の例外を生成しないことを宣言し、より最適なコード生成を可能にします。
-⁠o出力する実行可能ファイルの名前を指定します。
-⁠O <level>コード最適化レベルを指定します。<level>は0、1、2、3、4です。
-⁠stdpar標準C++およびFortranの並列化およびNVIDIA GPUへのオフロードを有効にします。デフォルトは-stdpar=gpuです。
-⁠tp <target>コンパイルホストCPU以外のCPUターゲットを指定する。
-⁠Wl,<option>コンパイラ・ドライバは、指定されたオプションをリンカに渡します。
next-gpu-technical


執筆中!のためお待ちください。