0. 概要

本チュートリアルは、OCIコンソールから必要なリソースを順次OCI上にデプロイしてその上でソフトウェア環境を手動で構築する方法で、 Docker Community EditionNVIDIA Container Toolkit を使用する分散機械学習に対応するコンテナ実行環境をGPUクラスタ上に構築、複数ノードに跨るGPU間の通信性能を NCCL(NVIDIA Collective Communication Library) の通信性能計測プログラム NCCL Tests で検証後、分散機械学習の稼働確認として TensorFlowMultiWorkerMirroredStrategy を使用するサンプルプログラムを実行、その性能を検証します。

本チュートリアルで構築するGPUクラスタの構成を以下に示します。

[GPUノード]

[Bastionノード]

[ソフトウェア]

  • コンテナランタイム : Docker Community Edition 26.1.3
  • NVIDIA Container Toolkit : 1.15.0

[クラスタ管理]

  • 共有ストレージ : BastionノードをNFSサーバとするGPUクラスタ内ホームディレクトリ共有

※1) OCI HPCテクニカルTips集クラスタネットワーキングイメージの選び方1. クラスタネットワーキングイメージ一覧 のイメージ No.7 です。

システム構成図

このチュートリアルで作成する環境は、ユーザ管理、ホスト名管理、ファイル共有、プログラム開発環境、コンテナオーケストレーション等、必要なソフトウェア環境をこの上に整備し、ご自身の要件に沿ったGPUクラスタを構築する際の基礎インフラストラクチャとして利用することが可能です。
なお、これらのクラスタ管理に必要なソフトウェアの導入までを自動化する HPCクラスタスタック も利用可能で、詳細は OCI HPCチュートリアル集 のカテゴリ 機械学習環境 のチュートリアルでクラスタ管理機能が有りとなっているチュートリアルを参照ください。

所要時間 : 約2時間

前提条件 : GPUクラスタを収容する コンパートメント ( ルート・コンパートメント でもOKです)の作成と、このコンパートメントに対する必要なリソース管理権限がユーザーに付与されていること。

注意 : 本コンテンツ内の画面ショットは、現在のOCIコンソール画面と異なっている場合があります。


1. GPUクラスタ作成事前作業

1-0. 概要

本章は、GPUノードをTCP接続する 仮想クラウド・ネットワーク と、インターネットから直接アクセス出来ないプライベートサブネットに接続するGPUノードにログインする際の踏み台となるBastionノードを、GPUクラスタ作成前に予め用意します。

1-1. 仮想クラウド・ネットワーク作成

本章は、GPUノードをTCP接続する 仮想クラウド・ネットワーク を作成します。
仮想クラウド・ネットワーク の作成は、 OCIチュートリアルその2 - クラウドに仮想ネットワーク(VCN)を作る の手順に従い、以下のリソースを作成します。

  • 仮想クラウド・ネットワーク (10.0.0.0/16)
  • パブリックサブネット(10.0.1.0/24)
  • プライベートサブネット(10.0.2.0/24)
  • インターネット・ゲートウェイ (パブリックサブネットにアタッチ)
  • NATゲートウェイ (プライベートサブネットにアタッチ)
  • サービス・ゲートウェイ (プライベートサブネットにアタッチ)
  • ルート表 x 2(パブリックサブネットとプライベートサブネットにアタッチ)
  • セキュリティリスト x 2(パブリックサブネットとプライベートサブネットにアタッチ)

作成後、 セキュリティリスト が以下となるように修正します。

サブネット 通信方向 ステートレス ソース IPプロトコル ソース・ポート範囲 宛先ポート範囲
パブリック イングレス いいえ 0.0.0.0/0
(※2)
TCP All 22
    いいえ 10.0.0.0/16 全てのプロトコル - -
  イグレス いいえ 0.0.0.0/0 全てのプロトコル - -
プライベート イングレス いいえ 10.0.0.0/16 全てのプロトコル - -
  イグレス いいえ 0.0.0.0/0 全てのプロトコル - -

※2)この設定により、BastionノードへのSSHアクセスをインターネット上の全てのIPアドレスに許可していますが、これを自身のサイトのIPアドレスに限定することで、不正アクセスを防ぐことが可能です。

1-2. Bastionノード作成

本章は、GPUノードにログインする際の踏み台となるBastinノードを作成し、必要なセットアップ作業を実施します。

Bastionノードの作成は、 OCIチュートリアルその3 - インスタンスを作成する の手順を参考に、ご自身の要件に沿ったインスタンスを先の手順で 仮想クラウド・ネットワーク を作成した コンパートメント とパブリックサブネットを指定して作成します。
本チュートリアルは、以下属性のインスタンスをBastionノードとして作成します。

  • イメージOracle Linux 8.9
  • シェイプVM.Standard.E4.Flex (任意のコア数・メモリ容量)
  • SSHキーの追加 : Bastionノードにログインする際使用するSSH秘密鍵に対応する公開鍵

次に、作成したBastionノードにopcユーザでSSHログインして以下コマンドを実行、SSH鍵ペアを作成してこの公開鍵を authorized_keys に登録します。
このSSH鍵は、BastionノードからGPUノードにログインする際や、GPUノード間のMPIプログラム実行時に使用します。

$ ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub | tee -a ~/.ssh/authorized_keys

次に、以降作成するGPUノードの名前解決をインスタンス名で行うため、 OCI HPCテクニカルTips集計算/GPUノードの効果的な名前解決方法 の手順を実施します。

次に、以降作成するGPUノードで実施する手順を pdsh を使用して効率よく進めるため、 OCI HPCテクニカルTips集pdshで効率的にクラスタ管理オペレーションを実行1. pdshインストール・セットアップ の手順を実施し、 pdsh をインストール・セットアップします。
なおこの手順は、該当する手順を全てのGPUノードで実施する場合、必要ありません。

次に、以下コマンドをopcユーザで実行し、GPUクラスタ内でホームディレクトリをNFS共有するためNFSサーバとして構成します。

$ echo "/home 10.0.0.0/16(rw,sync,no_root_squash)" | sudo tee -a /etc/exports
$ sudo systemctl enable --now nfs-server rpcbind

次に、以下のファイルを新規に作成後

[ /etc/firewalld/zones/trusted.xml ]

<?xml version="1.0" encoding="utf-8"?>
<zone target="ACCEPT">
  <short>Trusted</short>
  <description>All network connections are accepted.</description>
  <source address="10.0.0.0/16"/>
</zone>

opcユーザで以下コマンドを実行し、プライベートサブネットからのNFSアクセスをファイアーウォールに許可します。

$ sudo systemctl restart firewalld

2. GPUクラスタ作成

2-0. 概要

クラスタ・ネットワーク は、作成時に指定する インスタンス構成 とノード数を基に インスタンス・プール がGPUノードをデプロイし、これを クラスタ・ネットワーク に接続します。

またGPUノードのOSレベルのカスタマイズは、 cloud-init を使用して自動化することで、デプロイ後の作業を軽減します。

以上より、GPUクラスタの作成は、以下の手順を経て行います。

  • cloud-init 設定ファイル( cloud-config )作成
  • インスタンス構成 作成
  • クラスタ・ネットワーク 作成

2-1. cloud-config作成

本章は、 cloud-init 設定ファイル( cloud-config )を作成します。

本チュートリアルは、 cloud-init を以下の目的で使用します。

  • タイムゾーンをJSTに変更
  • NVMe SSDローカルディスク領域ファイルシステム作成
  • firewalld停止
  • ルートファイルシステム拡張
  • パブリックサブネットのドメイン名を search 行に追加
  • BastionノードのホームディレクトリをNFSマウント

以下は、本チュートリアルで使用する cloud-config で、OCIコンソールを実行している端末上にテキストファイルで保存します。

#cloud-config
#
# Change time zone to JST
timezone: Asia/Tokyo

runcmd:
#
# NVMe local storage setting
  - vgcreate nvme /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1
  - lvcreate -l 100%FREE nvme
  - mkfs.xfs -L localscratch /dev/nvme/lvol0
  - mkdir -p /mnt/localdisk
  - echo "LABEL=localscratch /mnt/localdisk/ xfs defaults,noatime 0 0" >> /etc/fstab
  - mount /mnt/localdisk
#
# Stop firewalld
  - systemctl disable --now firewalld
#
# Expand root file system to those set by instance configuration
  - /usr/libexec/oci-growfs -y
#
# Add public subnet to DNS search
  - sed -i '/^search/s/$/ public.vcn.oraclevcn.com/g' /etc/resolv.conf
  - chattr -R +i /etc/resolv.conf
#
# NFS mount setting
  - echo "bastion:/home /home nfs defaults,vers=3 0 0" >> /etc/fstab
  - mount /home

2-2. インスタンス構成作成

本章は、 インスタンス構成 を作成します。

  1. OCIコンソールにログインし、GPUクラスタをデプロイするリージョンを選択後、 コンピュートインスタンス構成 とメニューを辿ります。

  2. 表示される以下画面で、インスタンス構成の作成 ボタンをクリックします。

    画面ショット

  3. 表示される インスタンス構成の作成 画面で、以下の情報を入力し 作成 ボタンをクリックします。なお、ここに記載のないフィールドは、デフォルトのままとします。

    3.1 インスタンス構成情報 フィールド

    • 名前 :インスタンス構成に付与する名前
    • コンパートメントに作成 :インスタンス構成を作成するコンパートメント

    画面ショット

    3.2 インスタンスの作成先のコンパートメント フィールド:インスタンスをデプロイするコンパートメント

    画面ショット

    3.3 配置 フィールド

    • 可用性ドメイン :インスタンスをデプロイする可用性ドメイン

    画面ショット

    3.4 イメージとシェイプ フィールド

    画面ショット

    • イメージ :Oracle Linux - GPU Cluster Networking Image (イメージの変更 ボタンをクリックして表示される以下 イメージの選択 サイドバーで Marketplace アイコンを選択し検索フィールドに gpu と入力して表示される Oracle Linux - GPU Cluster Networking Image を選択し イメージ・ビルド フィールドで OracleLinux-8-OCA-RHCK-OFED-23.10-2.1.3.1-GPU-550-CUDA-12.4-2024.05.08-0 を選択し イメージの選択 ボタンをクリック)

      画面ショット

    • ShapeBM.GPU4.8/BM.GPU.A100-v2.8Change Shape ボタンをクリックして表示される以下 すべてのシェイプの参照 サイドバーで ベア・メタル・マシン をクリックして表示される BM.GPU4.8/BM.GPU.A100-v2.8 を選択し 次のドキュメントを確認した上でこれに同意します チェックボックスをチェックし シェイプの選択 ボタンをクリック)

      画面ショット

    3.5 ネットワーキング フィールド

    • プライマリ・ネットワーク : 先に作成したVCNを選択
    • サブネット :先に作成したプライベートサブネットを選択

    画面ショット

    3.6 SSHキーの追加 フィールド

    • SSHキー :先にBastionノードで作成したSSH鍵の公開鍵( 以下 公開キーの貼付け ラジオボタンを選択することで入力フィールドを表示)

    画面ショット

    3.7 ブート・ボリューム フィールド

    • ブート・ボリューム・サイズ(GB) : 200(※2)
      • カスタム・ブート・ボリューム・サイズを指定します チェックボックスをチェックすると指定可能

    画面ショット

    ※2)通常GPUノードは、様々な機械学習用ソフトウェアやコンテナイメージを格納する必要があるため、少なくとも200 GBの ブート・ボリューム サイズとします。

    3.8 管理 フィールド(以下 拡張オプションの表示 ボタンを選択して表示)

    画面ショット

    • cloud-initスクリプト :先に作成した cloud-init 設定ファイル( cloud-config )を選択( 参照 ボタンでファイルを選択)

    画面ショット

    3.9 Oracle Cloudエージェント フィールド(以下 Oracle Cloudエージェント タブを選択して表示)

    • Compute HPC RDMA Auto-Configuration :チェック
    • Compute HPC RDMA Authentication :チェック

    画面ショット

2-3. クラスタ・ネットワーク作成

本章は、 クラスタ・ネットワーク を作成します。

  1. OCIコンソールにログインし、GPUクラスタをデプロイするリージョンを選択後、 コンピュートクラスタ・ネットワーク とメニューを辿ります。

  2. 表示される以下画面で、クラスタ・ネットワークの作成 ボタンをクリックします。

    画面ショット

  3. 表示される クラスタ・ネットワークの作成 画面で、以下の情報を入力し クラスタ・ネットワークの作成 ボタンをクリックします。なお、ここに記載のないフィールドは、デフォルトのままとします。

    3.1 名前 フィールド:クラスタ・ネットワークに付与する名前

    画面ショット

    3.2 コンパートメントに作成 フィールド:クラスタ・ネットワークをデプロイするコンパートメント

    画面ショット

    3.2 可用性ドメイン フィールド:クラスタ・ネットワークをデプロイする可用性ドメイン

    画面ショット

    3.3 ネットワーキングの構成 フィールド

    • 仮想クラウド・ネットワーク :先に作成したVCNを選択
    • サブネット :先に作成したプライベートサブネットを選択

    画面ショット

    3.4 インスタンス・プールの構成 フィールド

    画面ショット

  4. 表示される以下 クラスタ・ネットワーク作業リクエスト 画面で、左上のステータスが プロビジョニング中 と表示されれば、クラスタ・ネットワークとGPUノードの作成が実施されています。

    画面ショット

    ステータスが 実行中 となれば、 クラスタ・ネットワーク とGPUノードの作成が完了しています。


3. GPUノード確認

3.0. 概要

本章は、デプロイされたGPUノードにログインし、環境を確認します。

3.1. GPUノードログイン

GPUノードは、プライベートサブネットに接続されており、インターネットからログインすることが出来ないため、Bastionノードを経由してSSHログインします。
BastionノードからGPUノードへのログインは、GPUノードのインスタンス名を使用します。

GPUノードのインスタンス名は、OCIコンソールでGPUノードをデプロイしたリージョンを選択後、 コンピュートインスタンス とメニューを辿り、以下のインスタンス一覧からそのインスタンス名を確認します。
またこの画面は、GPUノードのIPアドレスも表示しており、これを使用してBastionノードからSSHログインすることも可能です。

画面ショット

GPUノードへのログインは、以下のようにBastionノードからopcユーザでSSHログインします。

$ ssh -oStrictHostKeyChecking=accept-new inst-xxxxx-gpu4-ol89

3.2. cloud-init完了確認

cloud-init は、GPUノードが起動してSSHログインできる状態であっても、その処理が継続している可能性があるため、以下コマンドでそのステータスを表示し、 done となっていることで cloud-init の処理完了を確認します。
ステータスが running の場合は、 cloud-init の処理が継続中のため、処理が完了するまで待ちます。

$ pdsh -g all 'sudo cloud-init status' | dshbak -c
----------------
inst-xxxxx-gpu4-ol89,inst-yyyyy-gpu4-ol89
----------------
status: done
$

3-3. タイムゾーン確認

以下コマンドをBastionノードのopcユーザで実行し、タイムゾーンがJSTになっていることを確認します。

$ pdsh -g all 'date' | dshbak -c
----------------
inst-xxxxx-gpu4-ol89,inst-yyyyy-gpu4-ol89
----------------
Mon Jan 29 12:08:00 JST 2024
$

3-4. ファイルシステム確認

以下コマンドをBastionノードのopcユーザで実行し、ルートファイルシステムが指定のサイズとなっていること、Bastionノードの /home がNFSで /home にマウントされていること、及びNVMe SSDローカルディスクが /mnt/localdisk にマウントされていることを確認します。

$ pdsh -g all 'sudo df -h / /home /mnt/localdisk' | dshbak -c
----------------
inst-xxxxx-gpu4-ol89,inst-yyyyy-gpu4-ol89
----------------
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/ocivolume-root  189G   39G  151G  21% /
bastion:/home                36G   11G   25G  31% /home
/dev/mapper/nvme-lvol0       25T  177G   25T   1% /mnt/localdisk
$

3-5. ファイアーウォール停止確認

以下コマンドをBastionノードのopcユーザで実行し、ファイアーウォールが停止されていることを確認します。

$ pdsh -g all 'sudo systemctl status firewalld | grep -e Active -e disabled' | dshbak -c
----------------
inst-xxxxx-gpu4-ol89,inst-yyyyy-gpu4-ol89
----------------
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
$

3-6. クラスタ・ネットワーク接続用ネットワークインターフェース確認

以下コマンドをBastionノードのopcユーザで実行し、 クラスタ・ネットワーク 接続用の16個のネットワークインターフェース(rdmax)にTCP/IP接続用のネットワークインターフェース(eth0)と4フィールド目が同じ10.224.[0 - 15].x/12のIPアドレスが設定されていることを確認します。
なお、このIPアドレス設定が完了するまで、GPUノードにログイン可能となってから10分程度を要します。

$ pdsh -g all 'ip a | grep -e eth0 -e rdma | grep inet' | dshbak -c
----------------
inst-xxxxx-gpu4-ol89
----------------
    inet 10.0.2.117/24 brd 10.0.2.255 scope global dynamic eth0
    inet 10.224.0.117/12 brd 10.239.255.255 scope global noprefixroute rdma0
    inet 10.224.1.117/12 brd 10.239.255.255 scope global noprefixroute rdma1
    inet 10.224.2.117/12 brd 10.239.255.255 scope global noprefixroute rdma2
    inet 10.224.3.117/12 brd 10.239.255.255 scope global noprefixroute rdma3
    inet 10.224.4.117/12 brd 10.239.255.255 scope global noprefixroute rdma4
    inet 10.224.5.117/12 brd 10.239.255.255 scope global noprefixroute rdma5
    inet 10.224.6.117/12 brd 10.239.255.255 scope global noprefixroute rdma6
    inet 10.224.7.117/12 brd 10.239.255.255 scope global noprefixroute rdma7
    inet 10.224.8.117/12 brd 10.239.255.255 scope global noprefixroute rdma8
    inet 10.224.9.117/12 brd 10.239.255.255 scope global noprefixroute rdma9
    inet 10.224.10.117/12 brd 10.239.255.255 scope global noprefixroute rdma10
    inet 10.224.11.117/12 brd 10.239.255.255 scope global noprefixroute rdma11
    inet 10.224.12.117/12 brd 10.239.255.255 scope global noprefixroute rdma12
    inet 10.224.13.117/12 brd 10.239.255.255 scope global noprefixroute rdma13
    inet 10.224.14.117/12 brd 10.239.255.255 scope global noprefixroute rdma14
    inet 10.224.15.117/12 brd 10.239.255.255 scope global noprefixroute rdma15
----------------
inst-yyyyy-gpu4-ol89
----------------
    inet 10.0.2.17/24 brd 10.0.2.255 scope global dynamic eth0
    inet 10.224.0.17/12 brd 10.239.255.255 scope global noprefixroute rdma0
    inet 10.224.1.17/12 brd 10.239.255.255 scope global noprefixroute rdma1
    inet 10.224.2.17/12 brd 10.239.255.255 scope global noprefixroute rdma2
    inet 10.224.3.17/12 brd 10.239.255.255 scope global noprefixroute rdma3
    inet 10.224.4.17/12 brd 10.239.255.255 scope global noprefixroute rdma4
    inet 10.224.5.17/12 brd 10.239.255.255 scope global noprefixroute rdma5
    inet 10.224.6.17/12 brd 10.239.255.255 scope global noprefixroute rdma6
    inet 10.224.7.17/12 brd 10.239.255.255 scope global noprefixroute rdma7
    inet 10.224.8.17/12 brd 10.239.255.255 scope global noprefixroute rdma8
    inet 10.224.9.17/12 brd 10.239.255.255 scope global noprefixroute rdma9
    inet 10.224.10.17/12 brd 10.239.255.255 scope global noprefixroute rdma10
    inet 10.224.11.17/12 brd 10.239.255.255 scope global noprefixroute rdma11
    inet 10.224.12.17/12 brd 10.239.255.255 scope global noprefixroute rdma12
    inet 10.224.13.17/12 brd 10.239.255.255 scope global noprefixroute rdma13
    inet 10.224.14.17/12 brd 10.239.255.255 scope global noprefixroute rdma14
    inet 10.224.15.17/12 brd 10.239.255.255 scope global noprefixroute rdma15
$

なお、後に実行する NCCL Tests の起動コマンドで設定している NCCL_IB_HCA 環境変数に指定のRDMAリンク名( mlx5_xx )は、以下のように先の クラスタ・ネットワーク 接続用のネットワークインターフェースに対応しています。

$ pdsh -g all 'rdma link show | grep rdma' | dshbak -c
----------------
inst-xxxxx-gpu4-ol89,inst-yyyyy-gpu4-ol89
----------------
link mlx5_6/1 state ACTIVE physical_state LINK_UP netdev rdma0 
link mlx5_7/1 state ACTIVE physical_state LINK_UP netdev rdma1 
link mlx5_8/1 state ACTIVE physical_state LINK_UP netdev rdma2 
link mlx5_9/1 state ACTIVE physical_state LINK_UP netdev rdma3 
link mlx5_0/1 state ACTIVE physical_state LINK_UP netdev rdma4 
link mlx5_1/1 state ACTIVE physical_state LINK_UP netdev rdma5 
link mlx5_2/1 state ACTIVE physical_state LINK_UP netdev rdma6 
link mlx5_3/1 state ACTIVE physical_state LINK_UP netdev rdma7 
link mlx5_14/1 state ACTIVE physical_state LINK_UP netdev rdma8 
link mlx5_15/1 state ACTIVE physical_state LINK_UP netdev rdma9 
link mlx5_16/1 state ACTIVE physical_state LINK_UP netdev rdma10 
link mlx5_17/1 state ACTIVE physical_state LINK_UP netdev rdma11 
link mlx5_10/1 state ACTIVE physical_state LINK_UP netdev rdma12 
link mlx5_11/1 state ACTIVE physical_state LINK_UP netdev rdma13 
link mlx5_12/1 state ACTIVE physical_state LINK_UP netdev rdma14 
link mlx5_13/1 state ACTIVE physical_state LINK_UP netdev rdma15 

4. コンテナ環境構築

本章は、 Docker Community EditionNVIDIA Container Toolkit を使用し、GPU利用可能なコンテナ環境を構築します。

以下コマンドをBastionノードのopcユーザで実行し、 Docker Community EditionNVIDIA Container Toolkit を全てのGPUノードにインストールしこれを起動します。

$ pdsh -g all 'sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo' | dshbak -c
----------------
inst-xxxxx-gpu4-ol89,inst-yyyyy-gpu4-ol89
----------------
Adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
$ pdsh -g all 'sudo dnf install -y docker-ce nvidia-container-toolkit > /dev/null 2>&1; echo $?' | dshbak -c
----------------
inst-xxxxx-gpu4-ol89,inst-yyyyy-gpu4-ol89
----------------
0
$ pdsh -g all 'sudo systemctl enable --now docker 2> /dev/null' | dshbak -c
$

次に、以下コマンドを全てのGPUノードのopcユーザで実行し、コンテナ上で BM.GPU4.8 が搭載する8個のGPUにアクセスできることを確認します。

$ sudo docker run --rm --gpus all nvcr.io/nvidia/base/ubuntu:22.04_20240212 nvidia-smi
Unable to find image 'nvcr.io/nvidia/base/ubuntu:22.04_20240212' locally
22.04_20240212: Pulling from nvidia/base/ubuntu
d66d6a6a3687: Pull complete 
24c2d4f7ea40: Pull complete 
9d30336abbd7: Pull complete 
feb1277c15aa: Pull complete 
3cf0dbeda93a: Pull complete 
99fc1e9ef206: Pull complete 
a8f7f8dfd4e2: Pull complete 
Digest: sha256:2a9f71d82aa4daac444c1b4b74d5d7b01f93eb23662c1236f89d817f083abecd
Status: Downloaded newer image for nvcr.io/nvidia/base/ubuntu:22.04_20240212
Mon Jul  1 02:58:34 2024       
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.15              Driver Version: 550.54.15      CUDA Version: 12.4     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA A100-SXM4-40GB          On  |   00000000:0F:00.0 Off |                    0 |
| N/A   38C    P0             81W /  400W |       0MiB /  40960MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
|   1  NVIDIA A100-SXM4-40GB          On  |   00000000:15:00.0 Off |                    0 |
| N/A   37C    P0             85W /  400W |       0MiB /  40960MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
|   2  NVIDIA A100-SXM4-40GB          On  |   00000000:51:00.0 Off |                    0 |
| N/A   34C    P0             81W /  400W |       0MiB /  40960MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
|   3  NVIDIA A100-SXM4-40GB          On  |   00000000:54:00.0 Off |                    0 |
| N/A   36C    P0             82W /  400W |       0MiB /  40960MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
|   4  NVIDIA A100-SXM4-40GB          On  |   00000000:8D:00.0 Off |                    0 |
| N/A   35C    P0             79W /  400W |       0MiB /  40960MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
|   5  NVIDIA A100-SXM4-40GB          On  |   00000000:92:00.0 Off |                    0 |
| N/A   35C    P0             81W /  400W |       0MiB /  40960MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
|   6  NVIDIA A100-SXM4-40GB          On  |   00000000:D6:00.0 Off |                    0 |
| N/A   34C    P0             78W /  400W |       0MiB /  40960MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
|   7  NVIDIA A100-SXM4-40GB          On  |   00000000:DA:00.0 Off |                    0 |
| N/A   36C    P0             85W /  400W |       0MiB /  40960MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
                                                                                         
+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|  No running processes found                                                             |
+-----------------------------------------------------------------------------------------+
$

5. NCCL Tests実行

本章は、 NGC Catalog から提供される TensorFlow NGC Container を起動し、このコンテナに含まれる NCCL とコンテナ上でビルドする NCCL Tests を使用し、Dockerコンテナ上で NCCL のGPU間通信性能を NCCL Tests で検証します。

この NCCL Tests 実行方法は、 標準ベンチマーク実行方法NCCL Tests実行方法 を参照してください。


6. MultiWorkerMirroredStrategyサンプルプログラム実行

本章は、 MultiWorkerMirroredStrategy サンプルプログラムを使用し、構築したGPUクラスタで分散機械学習プログラムを実行します。

ここで使用する MultiWorkerMirroredStrategy サンプルプログラムは、以下 TensorFlow 公式ドキュメントページのチュートリアルで使用されている、MNISTデータセットを使用した訓練を行うプログラムです。

https://www.tensorflow.org/tutorials/distribute/multi_worker_with_keras

マスターノードとスレーブノードで起動した双方のコンテナ上のrootユーザで、以下のプログラムを作成します。

$ cd /root
$ cat mnist.py
import os
import json
import tensorflow as tf
import numpy as np

def mnist_dataset(batch_size):
  (x_train, y_train), _ = tf.keras.datasets.mnist.load_data()
  x_train = x_train / np.float32(255)
  y_train = y_train.astype(np.int64)
  train_dataset = tf.data.Dataset.from_tensor_slices(
      (x_train, y_train)).shuffle(60000).repeat().batch(batch_size)
  return train_dataset

def build_and_compile_cnn_model():
  model = tf.keras.Sequential([
      tf.keras.layers.InputLayer(input_shape=(28, 28)),
      tf.keras.layers.Reshape(target_shape=(28, 28, 1)),
      tf.keras.layers.Conv2D(32, 3, activation='relu'),
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(128, activation='relu'),
      tf.keras.layers.Dense(10)
  ])
  model.compile(
      loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
      optimizer=tf.keras.optimizers.SGD(learning_rate=0.001),
      metrics=['accuracy'])
  return model

per_worker_batch_size = 64
tf_config = json.loads(os.environ['TF_CONFIG'])
num_workers = len(tf_config['cluster']['worker'])

strategy = tf.distribute.MultiWorkerMirroredStrategy()

global_batch_size = per_worker_batch_size * num_workers
multi_worker_dataset = mnist_dataset(global_batch_size)

with strategy.scope():
  multi_worker_model = build_and_compile_cnn_model()

multi_worker_model.fit(multi_worker_dataset, epochs=3, steps_per_epoch=70)

次に、マスターノードで起動したコンテナ上のrootユーザで以下コマンドを実行し、環境変数 TF_CONFIG を設定・確認します。
ここで、 worker セクションに指定するマスターノード(inst-xxxxx-gpu4-ol89)とスレーブノード(inst-yyyyy-gpu4-ol89)のホスト名は、自身の環境に合わせて修正します。

$ export TF_CONFIG="{\"cluster\": {\"worker\": [\"inst-xxxxx-gpu4-ol89:12345\", \"inst-yyyyy-gpu4-ol89:23456\"]}, \"task\": {\"type\": \"worker\", \"index\": 0}}"
$ echo $TF_CONFIG
{"cluster": {"worker": ["inst-xxxxx-gpu4-ol89:12345", "inst-yyyyy-gpu4-ol89:23456"]}, "task": {"type": "worker", "index": 0}}
$

次に、マスターノードで起動したコンテナ上のrootユーザで以下コマンドを実行します。
この時点では、スレーブノードの実行を待っている状態で、以下の出力で停止します。

$ python mnist.py
   :
2022-12-15 08:48:49.404772: I tensorflow/core/distributed_runtime/coordination/coordination_service_agent.cc:281] Coordination agent has successfully connected.

次に、スレーブノードで起動したコンテナ上のrootユーザで以下コマンドを実行し、環境変数 TF_CONFIG を設定・確認します。

$ export TF_CONFIG="{\"cluster\": {\"worker\": [\"inst-xxxxx-gpu4-ol89:12345\", \"inst-yyyyy-gpu4-ol89:23456\"]}, \"task\": {\"type\": \"worker\", \"index\": 1}}"
$ echo $TF_CONFIG
{"cluster": {"worker": ["inst-xxxxx-gpu4-ol89:12345", "inst-yyyyy-gpu4-ol89:23456"]}, "task": {"type": "worker", "index": 1}}
$

次に、スレーブノードで起動したコンテナ上のrootユーザで以下のコマンドを実行します。
これにより、待機していたマスターノードのワーカーとスレーブノードのワーカーが全16枚のGPUを使用してプログラムを実行します。

$ python mnist.py
2022-12-19 09:38:23.383751: I tensorflow/core/platform/cpu_feature_guard.cc:194] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE3 SSE4.1 SSE4.2 AVX
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2022-12-19 09:38:26.455413: I tensorflow/core/platform/cpu_feature_guard.cc:194] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE3 SSE4.1 SSE4.2 AVX
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2022-12-19 09:38:27.647393: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1637] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 38139 MB memory:  -> device: 0, name: NVIDIA A100-SXM4-40GB, pci bus id: 0000:0f:00.0, compute capability: 8.0
2022-12-19 09:38:27.649632: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1637] Created device /job:localhost/replica:0/task:0/device:GPU:1 with 38139 MB memory:  -> device: 1, name: NVIDIA A100-SXM4-40GB, pci bus id: 0000:15:00.0, compute capability: 8.0
2022-12-19 09:38:27.651996: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1637] Created device /job:localhost/replica:0/task:0/device:GPU:2 with 38139 MB memory:  -> device: 2, name: NVIDIA A100-SXM4-40GB, pci bus id: 0000:51:00.0, compute capability: 8.0
2022-12-19 09:38:27.654473: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1637] Created device /job:localhost/replica:0/task:0/device:GPU:3 with 38139 MB memory:  -> device: 3, name: NVIDIA A100-SXM4-40GB, pci bus id: 0000:54:00.0, compute capability: 8.0
2022-12-19 09:38:27.656586: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1637] Created device /job:localhost/replica:0/task:0/device:GPU:4 with 38139 MB memory:  -> device: 4, name: NVIDIA A100-SXM4-40GB, pci bus id: 0000:8d:00.0, compute capability: 8.0
2022-12-19 09:38:27.658573: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1637] Created device /job:localhost/replica:0/task:0/device:GPU:5 with 38139 MB memory:  -> device: 5, name: NVIDIA A100-SXM4-40GB, pci bus id: 0000:92:00.0, compute capability: 8.0
2022-12-19 09:38:27.660481: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1637] Created device /job:localhost/replica:0/task:0/device:GPU:6 with 38139 MB memory:  -> device: 6, name: NVIDIA A100-SXM4-40GB, pci bus id: 0000:d6:00.0, compute capability: 8.0
2022-12-19 09:38:27.662428: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1637] Created device /job:localhost/replica:0/task:0/device:GPU:7 with 38139 MB memory:  -> device: 7, name: NVIDIA A100-SXM4-40GB, pci bus id: 0000:da:00.0, compute capability: 8.0
   :
Epoch 1/3
   :
70/70 [==============================] - 7s 30ms/step - loss: 2.2694 - accuracy: 0.1422
Epoch 2/3
70/70 [==============================] - 2s 29ms/step - loss: 2.2036 - accuracy: 0.3489
Epoch 3/3
70/70 [==============================] - 2s 28ms/step - loss: 2.1268 - accuracy: 0.5488

7. GPUクラスタの削除

本章は、 クラスタ・ネットワーク を終了することで、作成した クラスタ・ネットワーク とGPUノードを削除します。

  1. OCIコンソールメニューから コンピュートクラスタ・ネットワーク を選択し、表示される以下画面で作成した クラスタ・ネットワーク終了 メニューをクリックします。

    画面ショット

クラスタ・ネットワーク状態終了済 となれば、削除が完了しています。

以上で、本チュートリアルは終了です。

更新日時: