C/C++の使い方(NVIDIA HPC Compiler)
2024年2月現在、遺伝研スパコンシステムではNVIDIA HPC SDK 23.7をシステムに導入しています。旧PGI Compilerは、NVIDIA HPC SDK内のNVIDIA HPC Compilerとして開発が継続されています。
バージョン23.7の各コンポーネントのバージョン等は23.7 リリースノードを参照してください。制限事項等については日本語のリリースノートを参照してください。
NVIDIA HPC SDKの利用を検討した方が良い場合としては、以下が考えられます。
- NVIDIA社製GPUを利用した各種最適化、高速化を図りたい場合。
- NVIDIA社製GPUの利用が前提となった各種オープンソースソフトウェアを最適化も考慮しつつビルドする場合
- OpenACCを利用したソースコードを利用し、GPUオフロードコードを生成したい場合
- 各種CPU(Intel,AMD,Arm,OpenPOWER)向けに最適化されたオブジェクトコードを生成して性能比較したい場合
- NVIDIA社製GPUを利用して高速化が図られたNVIDIAが開発する各種数値計算ライブラリを利用したい場合
- 分散深層学習のライブラリでNCCLを利用したい場合(ソースコードをダウンロードして自分でビルドした方が簡単な場合もあるとは思われる)
- InfiniBandのSHARPを利用したMPI集合通信のハードウェアオフロードが可能なMPIを利用したい場合(大規模MPI並列の場合)
- CUDAを利用したアプリケーション開発、デバッグを行いたい場合
遺伝研スパコンで利用可能なのは以下のコンポーネントです。
NVIDIA HPC SDKのコンポーネント概要
コンポーネント名 | 概要 |
---|---|
NVIDIA HPC Compiler | (旧)PGIコンパイラ。NVIDIAが現在開発。OpenMP,OpenACCに対応し、CPU(Intel,AMD,Arm,OpenPOWER)、NVIDIA GPUに対応した最適化コードを生成可能 |
MPI | OpenMPIベースでSHARPのハードウェアオフロードに対応したhpc-xとOpenMPIが同梱されている。 |
CUDA Toolkit | NVIDIA GPU対応のCUDAコンパイラ、ライブラリ、ヘッダファイルなど開発環境一式 |
NSight Systems | CPU,GPUのプロファイラ |
NSight Compute | CUDAカーネルのプロファイラ。GPU内のハードウェアカウンタを参照した詳細なプロファイリングが可能 |
NCCL | 分散深層学習用のコミュニケーションライブラリ |
NVSHMEM | OpenSHMEMをマルチGPU、マルチノード対応に拡張したソフトウェア |
cuBLAS | CUDA上のGPU対応BLAS |
cuFFT,cuFFTMp | GPU対応のFFT、マルチGPU対応のFFTライブラリ |
cuRAND | GPU対応の乱数生成ライブラリ |
cuSOLVER | cuBLASとcuSPARSEをベースにしたCUDA上の線形代数関数のパッケージ |
cuSPARSE | CUDA上の疎行列計算ライブラリ |
cuTENSOR,cuTENSORMg | CUDA上でテンソル計算を高速化する為のライブラリ MgはマルチGPU対応 |
NVPL ScalaPack | NVIDIAがエンハンスするScaLAPACK |
Thrust,CUB,libcu++ | CUDA対応C++テンプレートライブラリ群 |
また、NVIDIA HPC SDKは、以下のサイトからダウンロード可能です。
お手持ちの計算機で開発、デバッグを行い、大規模計算を遺伝研スパコンで行うといった利用方法も可能と考えます。また、NSight Systemsなどの GUIを利用するシステムを利用する場合は、解析情報を遺伝研スパコンで取得し、その結果を転送して手元の計算機上のNSight SystemsのGUIで表示すると いった利用形態をとることも可能です。
NVIDIA HPC Compiler
遺伝研スパコンでは、NVIDIA HPCコンパイラについてはデフォルトでコンパイラにパスが通っています。パスが通っていることを確認します。
which nvc
/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/compilers/bin/nvc
which nvc++
/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/compilers/bin/nvc++
which nvfortran
/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/compilers/bin/nvfortran
コマンドライン形式
利用可能なコンパイラは以下になります。
言語 | コマンド | コマンドライン | 言語規格・機能 |
---|---|---|---|
C | nvc | nvc [オプション] ファイル名 | ISO/ANSI C11 OpenMP,OpenACCサポート |
C++ | nvc++ | nvc++ [オプション] ファイル名 | ISO/ANSI C++17 OpenMP,OpenACCサポート |
fortran | nvfortran | nvfortran [オプション] ファイル名 |
利用可能なコンパイラオプション
汎用的な最適化オプションとしては-fastオプションを指定しておくことがベンダ推奨になっています。また-Minfoオプションはコンパイル時の最適化メッセージを出力する為のオプションで、これも状況を確認する為につけておくことを推奨します。また、プログラム内のグローバル最適化を有効にする為には、Interprocedual Analysisの機能を有効にします。 以上を纏めると、ベンダにより推奨されるオプション指定は以下のようになります。
nvc -fast -Mipa=fast,inline -Minfo test.c (Cコンパイラ)
nvc++ -fast -Mipa=fast,inline -Minfo test.cpp (C++コンパイラ)
プログラムによっては、さらにオプションを調整すると性能が向上する場合もありますが、専門的かつ大部な話題になりますのでここでは説明を省略します。詳細については開発元のドキュメントをご参照ください。
その他、よく利用される主なオプションについては以下のようになりま す。(下記は基本的に出典外部サイトの意訳です。用語等についても参照をお願いします。)
オプション | 機能 |
---|---|
-acc | OpenACC ディレクティブを使用して並列化を有効にします。 |
-fast | SIMD 機能をサポートするターゲットに対して一般的に最適なフラグのセットを作成します。ベクトルストリーミング SIMD 命令、キャッシュ・アライメント、flushz を使用できるようにする最適化オプションが組み込まれています。 |
-g | オブジェクト・モジュールにシンボリック・デバッグ情報を含めるようコンパイラに指示します。コマンドラインに-Oオプションがない限り、最適化レベルをゼロに設定します。逆に、DWARF情報を生成しないようにするには、-Mnodwarfオプションを使用します。 |
-gpu | コードが生成されるGPUの種類、対象となるCUDAのバージョン、その他GPUコード生成のいくつかの側面を制御します。 |
-help | 利用可能なオプションの情報を提供します。 |
-mcmodel=medium | 64ビットターゲット用のコード生成を有効にし、プログラムのデータ容量が4GBを超える場合に有効です。 |
-mp | OpenMPディレクティブを使用した並列化を有効にします。-mp=gpuはNVIDIA GPUを利用してOpenMP領域をオフロードする為に利用します。 |
-Mconcur | ループの自動並列化を有効にするようコンパイラに指示します。指定された場合、コンパイラは並列化可能であると判断したループを複数のCPUコアを使用して実行するため、ループの反復はマルチスレッド実行コンテキストで最適に実行されるように分割されます。 |
-Minfo | 標準エラーに情報を出力するようコンパイラに指示します。 |
-Minline | 関数のインライン化を可能にします。 |
-Mipa=fast,inline | プロシージャ間のグローバル解析と最適化を可能にします。 |
-Munroll | ループアンローラーを起動してループを展開し、各反復の間にループの複数のインスタンスを実行します。また、最適化レベルが 2 未満に設定されている場合、または -O や -g オプションが指定されていない場合、最適化レベルが 2 に設定されます。 |
-o | 出力する実行可能ファイル名を指定します。 |
-O level | コード最適化レベルを指定します。levelは0、1、2、3、4です。 |
OpenMPの利用
NVIDIA HPC CompilerではOpenMPが利用可能です。OpenMP4.0以降ではCPU以外へのオフロードにも対応しGPU、FPGAなどのアクセラレータ用の汎用並列規格にもなっています。現在OpenMPはIntel、AMD、NVIDIAがサポートしておりベンダ間での汎用的な並列規格になっています。 使用方法詳細については以下のサイトを参照してください。
OpenACCの利用
NVIDIA HPC Compilerでは、OpenACCが利用可能です。使用方法については以下のサイトをご参照ください。
OpenACC organizationにより仕様が策定されており、オープンな仕様になっています。かつてPGIがOpenACC organizationの主要なメンバとして仕様策定を行っていました。以下の外部サイトが参考になります。
Intel/AMD/NVIDIAのGPU間でのポータビリティを重視する場合OpenMPが利用される傾向があるようです。しかしNVIDIA GPU向けであれば、NVIDIAがOpenACCのサポートにより積極的ではあるため、OpenMPよりOpenACCのほうがより高性能のコードを生成できる傾向があるようです。
MPIの利用
NVIDIA HPC-SDK23.7では、以下の2つのMPI処理系がインストールされています。
- HPC-X
- OpenMPI 4.1.5
HPC-Xは、NVIDIAがOpenMPIをベースにして一部の集団通信をハードウェアオフロードできるようにしたものです。HPC-XはNVIDIAによってHPC-SDKに同梱されているソフトウェアの前提MPI処理系に指定されている場合があります。遺伝研スパコンでのインストール位置は以下の場所になります。
MPI処理系 | インストールディレクトリ |
---|---|
HPC-X | /opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15 |
OpenMPI 4.1.5 | /opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/openmpi4/openmpi-4.1.5 |
ただし、システム側で設定したデフォルトのパスでは他のMPI実装(Intel MPI)にパスが通っている為、利用したい場合は、 以下のようにしてください。
HPC-Xを利用したい場合は、以下のようにhpcx-init.shを読み込んだ後に、hpc_loadを入力してください。
$ which mpirun
/lustre7/software/intel_ubuntu/oneapi/mpi/2021.11/bin/mpirun
$ . /opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/hpcx-init.sh
$ hpcx_load
$ which mpirun
/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ompi/bin/mpirun
$ env |grep HPC
HPCX_HCOLL_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/hcoll
HPCX_CLUSTERKIT_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/clusterkit
HPCX_OSU_CUDA_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ompi/tests/osu-micro-benchmarks-5.8-cuda
HPCX_OSU_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ompi/tests/osu-micro-benchmarks-5.8
HPCX_MPI_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ompi
HPCX_OSHMEM_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ompi
HPCX_UCC_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ucc
HPCX_UCX_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ucx
HPCX_IPM_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ompi/tests/ipm-2.0.6
HPCX_SHARP_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/sharp
HPCX_IPM_LIB=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ompi/tests/ipm-2.0.6/lib/libipm.so
HPCX_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15
HPCX_NCCL_RDMA_SHARP_PLUGIN_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/nccl_rdma_sharp_plugin
HPCX_MPI_TESTS_DIR=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/hpcx/hpcx-2.15/ompi/tests
元に戻したい場合は、hpcx_unloadを入力してください。HPC-X用の環境設定が解除されます。
$ hpcx_unload
$ env |grep HPCX
$ which mpirun
/lustre7/software/intel_ubuntu/oneapi/mpi/2021.11/bin/mpirun
呼び出していた、mpirunがIntelのパスに戻ります。
OpenMPI 4.1.5の場合
PATHにCompiler Wrapperのパスを以下のように加え、MPIプログラムのコンパイルを実施してください。
export PATH=/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/openmpi4/openmpi-4.1.5/bin:$PATH
mpicc ソースコードファイル -o オブジェクトファイル
また、LD_LIBRARY_PATHに以下を加えてください。
/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/comm_libs/12.2/openmpi4/openmpi-4.1.5/lib
参考 using MPI(NVIDIA SDK Documantation)
CUDAの利用
CUDAはNVIDIAが開発するNVIDIA GPU用の並列プログラミングモデルです。OpenMP/OpenACCよりさらに低レイヤーでのGPUプログラミングを行うことが可能で、計算性能を重視するプログラマ向けのプログラミングモデルになります。NVIDIA HPC CompilerではCUDAコンパイラドライバnvccが同梱されています。
言語 | コマンド | コマンドライン | 言語規格・機能 |
---|---|---|---|
NVCC | nvcc | nvcc [オプション] ファイル名 | CUDA C/C++ Compiler driver |
遺伝研スパコンでのCUDA関連の環境について
コンポーネント | バージョン | 備考 |
---|---|---|
CUDA Driver | 12.1 | |
nvccコンパイラ | V12.2.91、V12.1.66 |
遺伝研スパコンではnvccコンパイラについては、事情によりOS付属のnvcc、CUDA付属のnvcc、HPC-SDK付属のnvccがインストールされていますので ご注意ください。nvccのインストール場所は以下になります。
HPC-SDKに付属のnvccコンパイラドライバ
/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/cuda/12.2/bin/nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Built on Tue_Jun_13_19:16:58_PDT_2023
Cuda compilation tools, release 12.2, V12.2.91
Build cuda_12.2.r12.2/compiler.32965470_0
CUDA12.1に付属のnvccコンパイラドライバ
/usr/local/cuda-12.1/bin/nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Built on Tue_Feb__7_19:32:13_PST_2023
Cuda compilation tools, release 12.1, V12.1.66
Build cuda_12.1.r12.1/compiler.32415258_0
ubuntu22.04のOSパッケージ内のnvccコンパイラドライバ
/usr/bin/nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2021 NVIDIA Corporation
Built on Thu_Nov_18_09:45:30_PST_2021
Cuda compilation tools, release 11.5, V11.5.119
Build cuda_11.5.r11.5/compiler.30672275_0
基本的にはCUDA付属のnvccを利用してください。何らかエラーが発生する場合は、HPC-SDK付属のnvccを利用して 切り分けてください。OS付属のものは導入しているCUDAドライバとバージョンが合わない為、利用しないでください。 また、cmakeなどのmakeの生成ツールを使用する場合、OSデフォルトの設定を参照してしまっている場合があります。指定したつもりが ないのに、Ver11.5との整合性エラーが出る場合は、OS付属のnvccが参照されてしまっていることを疑って、明示的に他の nvcc環境が参照されるようにcmakeのオプションを立てて指定してください。
環境変数としてCUDA_HOME(ソフトウェアによってはdeprecatedと表示される場合があります)、NVHPC_CUDA_HOMEを 指定する必要がある場合は、下記を指定してください。
/usr/local/cuda-12.1
現状、NVIDIA HPC-SDK付属のnvccにパスが通っている為、必要な場合、ドライバ付属のnvccに切り替えてください。
$ which nvcc
/opt/pkg/nvidia/hpc_sdk/Linux_x86_64/23.7/compilers/bin/nvcc
export PATH=/usr/local/cuda-12.1/bin:$PATH
which nvcc
/usr/local/cuda-12.1/bin/nvcc
また、LD_LIBRARY_PATHに以下のパスが入っているかを確認します。
/usr/local/cuda-12.1/lib64
入っていない場合は、以下の手順で追加してください。
export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH
nvccでのコンパイル方法含めての情報については以下のNVIDIAのサイトを参照してください。
NVIDIA CUDA Compiler Driver NVCC
CUDAプログラミング情報について
以下のNVIDIAのサイトの情報を参照してください。ここでは詳細は省略します。
CUDA C Programming Guide (NVIDIA)
NVIDIA Nsight Systems
NVIDIA Nsight Systemsはプロファイラです。CPU/GPUの利用率、メモリ使用量、データ転送量等で、プログラムの性能評価を行う際に利用します。
NVIDIA社のドキュメントサイト NVIDIA社のユーザガイド
基本的な利用方法としては、まず、遺伝研スパコン上でバッチジョブとしてプロファイルを取り、そのプロファイル情報をインタラクティブノード上で評価するという形になります。