NVIDIA HPC SDKをSingularityコンテナ化する

モチベーション

High Performance Computing用にコンパイラやGPU対応のライブラリ、ミドルウェアをパッケージとしてまとめている「NVIDIA HPC SDK」がある。このNVIDIA HPC SDKをSingularityコンテナとして利用したかったので、Singularityコンテナ作成手順をまとめた。

NGCから持ってくれば早いよ!との声もあるけど、Singularity理解を深めるため自力で作成することにした。

参考資料

以下のページを参考にした。

  • 本家、NVIDIAのdeveloper Webサイト配下にある、NVIDIA HPC SDKのページ。
  • GPU Technology Users Communityが公開しているNVIDIA HPC SDK技術情報のページ。インストール手順や環境構築後のサンプルソース等が役に立った。
  • sylabsのWebサイトにある「Docs」のUser GuideのDefinition Filesのページ。
  • ABCI User GroupのWebサイトに公開されているこの動画がSingularityの基礎を学ぶには良い。自分は、fakerootの本当の意味を知った。

手順

考え方

NVIDIA HPC SDKのSingularityコンテナをどうやって作成したら良いのか、分からなかったので、以下の手順で作成することにした。

  1. SingularityのSandbox上で、目的のコンテナを作成する。
  2. 1.で作成した手順を基にしてDefinition Fileを作成し、sifファイルを作る。

sandboxはミュータブル(mutable)で、指定したディレクトリ配下にファイルシステムのように作成される。作成されたディレクトリ、ファイルは作成したユーザ権限になっている。一方、sifファイルはイミュータブル(immutable)で、一旦作成したら、(例えば、pipでパッケージを)追加できない。

sandboxからsifを作成できるが、今回は、sandboxでの作成方法からDefinition Fileを作って、defファイルからsifファイルを作成する。モチベーションでも述べたが、このやり方を理解すれば、今後Singularityコンテナを作成する際に役立つと考えた。

SandboxでNVIDIA HPC SDKを作成

Sandboxを作成するまで

ベースとなるdockerイメージをnvidia/cudaのdockerhubから選択する。今回は「11.4.2-cudnn8-devel-ubuntu20.04」をベースとしたsandboxを作成する。

$ singularity build --sandbox ubuntu2004 docker:nvidia/cuda:11.4.2-cudnn8-devel-ubuntu20.04

これによって、ubuntu2004ディレクトが作成される。

次に、作成したsandboxイメージを起動する。

$ singularity shell --nv -f -w ubuntu2004

「-f」は「—fakeroot」、「-w」は「—writable」のことで、「-f」が重要でコンテナに追加されるようになる。

NVIDIA HPC SDKをインストールするのに、wgetが必要なこと、作成後にプログラムを試すために、viが必要になるので、次を実行。なお、ここからは、上記で起動したsingularity内での実行である。

Singularity> apt update
Singularity> apt install wget
Singularity> apt install vim

いよいよ、SDKをダウンロードし、インストールする。NVIDIA HPC SDKのインストールページの「Download」をクリックすると、NVIDIA HPC SDK 21.9 Downloadページに移動する。

このページで、license agreementをacceptし「Linux x86-64 DEB」をクリックすると、インストール手順が表示されるので、その通りをsandboxで実行する。

Singularity> wget https://developer.download.nvidia.com/hpc-sdk/21.9/nvhpc-21-9_21.9_amd64.deb \
https://developer.download.nvidia.com/hpc-sdk/21.9/nvhpc-2021_21.9_amd64.deb

上記を実行すると、ホームディレクトリに、nvhpc-2021_21.9_amd64.deb、nvhpc-21-9_21.9_amd64.debがダウンロードされている。引き続き、インストール手順の 2つ目を実行する。

Singularity> apt-get install ./nvhpc-21-9_21.9_amd64.deb ./nvhpc-2021_21.9_amd64.deb

環境変数を設定する

NVIDIA HPC SDKのインストールページの下の方にある、「1.3 エンドユーザー環境設定」の通り、環境変数を設定する。 なお、「21.9」の部分はインストールするSDKのバージョンである。

Singularity> NVARCH=`uname -s`_`uname -m`; export NVARCH
Singularity> NVCOMPILERS=/opt/nvidia/hpc_sdk; export NVCOMPILERS
Singularity> MANPATH=$MANPATH:$NVCOMPILERS/$NVARCH/21.9/compilers/man; export MANPATH
Singularity> PATH=$NVCOMPILERS/$NVARCH/21.9/compilers/bin:$PATH; export PATH

export PATH=$NVCOMPILERS/$NVARCH/21.9/comm_libs/mpi/bin:$PATH
export LD_LIBRARY_PATH=$NVCOMPILERS/$NVARCH/21.9/compilers/lib:$LD_LIBRARY_PATH
export MANPATH=$MANPATH:$NVCOMPILERS/$NVARCH/21.9/comm_libs/mpi/man

作成したSandboxを試す(コンパイルしてみる)

上記で環境変数を設定することで、関連のコマンドへのPATHが設定され、次の通り実行できる。

Singularity> nvaccelinfo

CUDA Driver Version:           11020
NVRM version:                  NVIDIA UNIX x86_64 Kernel Module  460.91.03  Fri Jul  2 06:04:10 UTC 2021

Device Number:                 0
Device Name:                   GeForce GTX TITAN
Device Revision Number:        3.5
Global Memory Size:            6379143168
Number of Multiprocessors:     14
Concurrent Copy and Execution: Yes
Total Constant Memory:         65536
Total Shared Memory per Block: 49152
Registers per Block:           65536
Warp Size:                     32
Maximum Threads per Block:     1024
Maximum Block Dimensions:      1024, 1024, 64
Maximum Grid Dimensions:       2147483647 x 65535 x 65535
Maximum Memory Pitch:          2147483647B
Texture Alignment:             512B
Clock Rate:                    875 MHz
Execution Timeout:             Yes
Integrated Device:             No
Can Map Host Memory:           Yes
Compute Mode:                  default
Concurrent Kernels:            Yes
ECC Enabled:                   No
Memory Clock Rate:             3004 MHz
Memory Bus Width:              384 bits
L2 Cache Size:                 1572864 bytes
Max Threads Per SMP:           2048
Async Engines:                 1
Unified Addressing:            Yes
Managed Memory:                Yes
Concurrent Managed Memory:     No
Default Target:                cc35

Device Number:                 1
Device Name:                   Quadro K2000
Device Revision Number:        3.0
Global Memory Size:            2093809664
Number of Multiprocessors:     2
Concurrent Copy and Execution: Yes
Total Constant Memory:         65536
Total Shared Memory per Block: 49152
Registers per Block:           65536
Warp Size:                     32
Maximum Threads per Block:     1024
Maximum Block Dimensions:      1024, 1024, 64
Maximum Grid Dimensions:       2147483647 x 65535 x 65535
Maximum Memory Pitch:          2147483647B
Texture Alignment:             512B
Clock Rate:                    954 MHz
Execution Timeout:             Yes
Integrated Device:             No
Can Map Host Memory:           Yes
Compute Mode:                  default
Concurrent Kernels:            Yes
ECC Enabled:                   No
Memory Clock Rate:             2000 MHz
Memory Bus Width:              128 bits
L2 Cache Size:                 262144 bytes
Max Threads Per SMP:           2048
Async Engines:                 1
Unified Addressing:            Yes
Managed Memory:                Yes
Concurrent Managed Memory:     No
Default Target:                cc30

自分の環境の 2枚差しの情報が表示される。ご覧の通りkepler世代、最新のGPUカードが欲しい!

NVIDIA HPC SDK 21.9のリリースノートには、Keplerアーキテクチャのサポートは、21.3以降、非推奨(deprecated)だった、とある。

次に、「1.4 コンパイラの利用」の通り、C、C++、Fortranのプログラムを実行してみた。

C、C++に関しては、include文を修正した。

C
include <stdio.h>
int main() {
	printf("hello, world!\n");
	return 0;
}
Singularity> nvc -o c_hello hello.c
C++
#include <iostream>
int main() {
	std::cout << "hello, world!\n";
	return 0;
}
Singularity> nvc++ -o cpp_hello hello.cpp
Fortran
print *, "Hello, world!"
end
Singularity> nvfortran -o f_hello hello.f90 -V

Definition Fileからsifファイルを作成

Defファイル

前節で実行した、sandbox作成までの手順を振り返って、次のhpc_sdk.defファイルを作成。

# NVIDIA HPC SDK 21.9(現時点の最新版)が動く、singularityコンテナを作成する。

Bootstrap:	docker
FROM:	nvidia/cuda:11.4.2-cudnn8-devel-ubuntu20.04

%post
	apt update -y && apt -y install wget vim
	wget https://developer.download.nvidia.com/hpc-sdk/21.9/nvhpc-21-9_21.9_amd64.deb \
	https://developer.download.nvidia.com/hpc-sdk/21.9/nvhpc-2021_21.9_amd64.deb
	apt-get -y install ./nvhpc-21-9_21.9_amd64.deb ./nvhpc-2021_21.9_amd64.deb

%environment
	NVARCH=`uname -s`_`uname -m`; export NVARCH
	NVCOMPILERS=/opt/nvidia/hpc_sdk; export NVCOMPILERS
	MANPATH=$MANPATH:$NVCOMPILERS/$NVARCH/21.9/compilers/man; export MANPATH
	PATH=$NVCOMPILERS/$NVARCH/21.9/compilers/bin:$PATH; export PATH
	export PATH=$NVCOMPILERS/$NVARCH/21.9/comm_libs/mpi/bin:$PATH
	export LD_LIBRARY_PATH=$NVCOMPILERS/$NVARCH/21.9/compilers/lib:$LD_LIBRARY_PATH
	export MANPATH=$MANPATH:$NVCOMPILERS/$NVARCH/21.9/comm_libs/mpi/man

sifファイル作成

$ sudo singularity build hpc_sdk.sif hpc_sdk.def

viのmanページの作成辺りでwarningが出てたが、以下でSingularityコンテナが動いた。

$ singularity shell --nv hpc_sdk.sif

起動したsingularityで、nvaccelinfoを実行すると、正常に実行された。環境変数もきちんと設定されている。

今後に向けて

今回のSingularityコンテナ作成を通じて、sandbox環境で試行錯誤しながら目的のコンテナを作成し、通常運用ではsifファイルを用意して実行させるという、一通りの手順を学んだ。

AI系ではコンテナ環境を作成後も必要なパッケージがあり、追加でインストールすることがある。暫くsandbox環境で試して、頃合いを見てsifにするという、流れを想定した手順を理解できた。実際にはハマること(hustleする必要)もあるとは思うが。


も参照してください