10分で準備するPyTorchとTensorFlowが使えるGPU仮想マシン

**(2024/10/29 更新) 近日中にリリース予定のNVIDIA RTX 4000 Adaインスタンスに合わせて記事を更新しました。一部古いGPUインスタンスであるRTX 6000のスクリーンショットや説明が含まれていますが、適宜読み替えてくださいますようお願いいたします**

ディープラーニングのフレームワークとして、Meta(旧Facebook)のPyTorchとGoogleのTensorFlowが高い人気を博しています。ディープラーニングモデルの開発・トレーニングプロセスには実質的にGPUの使用が必須ですが、これらのフレームワークでGPUを使えるようにするための環境構築や、PyTorchとTensorFlowをひとつの環境に共存させる準備は意外と手間がかかります。この記事ではAkamai Connected Cloud (旧名Linode)を使用して、GPU対応のPyTorchとTensorFlowがインストールされた環境を約10分で用意する方法を紹介します。本記事の手順によって、普段Linuxサーバーの環境構築をしていない方でも容易に専用のディープラーニング環境をクラウド上にセットアップできます。

# Akamai Connected Cloud (旧名Linode)とは

[Akamai Connected Cloud (ACC / 旧名Linode)](https://www.linode.com/)は、2022年2月にAkamaiが買収したクラウドコンピューティングサービスです。ACCは価格が安いことに加えて、予測可能なフラット・プライシング・モデルを採用しており、価格内にSSDストレージのほか、しばしば高額になりがちなネットワーク転送の費用が含まれております。リージョンごとの価格差もないので、コストの予測がしやすい価格体系になっています。たとえば、GPUとしてNVIDIA RTX 4000 Adaを搭載したメモリ16GBの仮想マシンは、500GBのSSDストレージ、1TB分のネットワーク転送量まで含めて月350ドル(2024年10月現在、以降同様)です。使用料は1時間単位で課金され、左記のタイプの仮想マシンであれば1時間あたり0.52ドルです。(1時間未満は1時間を単位として切り上げられます)

ACCの提供する[Cloud Estimator](https://www.linode.com/ja/estimator/)というツールで「GPU」を選択することで、他社クラウドと概算での価格比較ができます。

# この記事で構築する環境

この記事では、NVIDIAのGPUに対応したコンテナ仮想化プラットフォームであるDocker Engine Utility for NVIDIA (nvidia-docker)をACC上のGPUインスタンスにセットアップし、そこに[NGC Container](https://catalog.ngc.nvidia.com/containers)と呼ばれる、FacebookやGoogleが公式に提供しているディープラーニング用コンテナをデプロイします。これらのインストールにはACC独自のデプロイメント自動化機能であるStackScriptsを使い、ACC、Docker、NGC Containerなどの関連技術に精通していないくても約10分で環境を構築することができます。

https://qiita.com/isss802/items/d6e59063d3473659983d

![NVIDIA Container Toolkit](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/ac05fe6a-e941-7518-c032-4a64bad9b929.png) 
**https://github.com/NVIDIA/nvidia-docker/**

この手順で構築した環境には、非常に高い認識精度で話題になった音声認識モデルである[OpenAI Whisper](https://openai.com/blog/whisper/)を使えるサンプルを含めていますので、自分自身でディープラーニングモデルの開発をしない方でも、GPUインスタンスのメリットを体験することができます。
![Voice Recognition with OpenAI Whisper](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/85042154-cf09-5e89-4b13-c339a8cd2da8.png)
また、今回使うStackScriptにObject Storageの情報を与えておくと、PyTorchやTensorFlowのコンテナが別途準備したObject Storageを自動的にマウントするので、トレーニングデータの取り出しやディープラーニングモデルの保管に便利です。(この設定は任意で、Object Storageの準備は必須ではありません)

# PyTorchとTensorFlowが使えるGPU仮想マシンのインストール

まずは以下のリンクから事前に準備しておいたStackScriptを開きます。このStackScriptがnvidia-docker、PyTorch、TensorFlowを自動的にインストールします。(リンク先にアクセスするにはACCのアカウントにログインしておく必要があります)

**deeplearning-gpu**
https://cloud.linode.com/stackscripts/1102035

※もし何らかの理由でこのStackScriptを開くことができなければ、このStackScriptの中身を[GitHubにもアップロードしている](https://github.com/hokamoto/stackscripts/blob/main/deeplearning.sh)のでご使用ください。


「Deploy New Linode」をクリックします
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/5fbe0e18-70fb-08e6-e8cc-24aa6ba00685.png)

StackScriptにはUDF(ユーザー定義フィールド)という、デプロイメントにあたって必要なパラメータを自動的にWebの入力フォームにする機能があります。このStackScriptでは、仮想マシンにSSHログインできる非rootのユーザーのログイン情報や、Object Storageを外部ストレージとしてマウントするために必要なAccess Keyを仮想マシンのデプロイメント時に指定できるようになっています。なお、Object Storageをマウントする場合は事前にバケットを作成してAccess Keyを取得しておく必要があります。手順の一例として以下の記事も参考にしてください。また、日本からの利用であれば、Object Storageはap-south-1 (シンガポール)リージョンに準備しておくことを推奨します。

https://qiita.com/isss802/items/3a4b9865c6f88373e437

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/34e9df87-8f70-b9ac-fa2b-e1da790e73ae.png)

仮想マシンを作成するリージョンと仮想マシンの種類を選択します。2024年10月現在、以下のリージョンでRTX 4000 Ada GPUインスタンスが使用できます。

- Seattle, WA, US
- Chicago, IL, US
- Paris, FR
- Osaka, JP

ここではシンガポールリージョンでDedicated 32 GB + RTX6000 x1を選択します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/a09d4815-5678-953f-5862-78693fd4ae6f.png)
仮想マシンの名前、rootパスワードを指定して「Create Linode」をクリックします
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/d6c4fdf6-f64d-c94e-8800-26a7112b37f9.png)
仮想マシンの管理ダッシュボードに画面が遷移するので、仮想マシンの状態がPROVISIONINGからRUNNINGになるまで数分待ちます。同じ画面に今作成した仮想マシンのIPアドレスが表示されているのでメモしておきます。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/bb48e8ff-d9f7-ba95-9804-ea5e21e587da.png)
これで仮想マシンが起動しました。起動した後はStackScriptに沿って必要なソフトウェアのインストールがバックグラウンドで自動的に進みます。インストールが終わるまで10分ほど待ってから次の「コンテナを起動する」に進みます。

# コンテナを起動する
それでは早速仮想マシンにログインしてみます。StackScriptによる環境構築が完了していると、以下のようなメッセージがログイン時に表示されます。このメッセージが表示されない場合はまだ環境構築が完了していない可能性があるので、いったんログアウトして数分待ってから再度ログインしてください。また、誤ってGPUを使えない仮想マシンで起動していると「GPU is not available. This StackScript should be used for GPU instances.」というメッセージが出るので、その場合はGPU付きの仮想マシンを使って手順を最初からやりなおしてください。
```console
% ssh root@139.162.XX.XX
root@139.162.XX.XX's password:

(中略)

##############################################################################
You can launch a Docker container with each of the following commands:

pytorch: Log into an interactive shell of a container with Python and PyTorch.
tensorflow: Log into an interactive shell of a container with Python and TensorFlow.
pytorch-notebook: Start Jupyter Notebook with PyTorch as a daemon. You can access it at http://[Instance IP address]/
tensorflow-notebook: Start Jupyter Notebook with TensorFlow as a daemon. You can access it at http://[Instance IP address]/

Other commands:
stop-all-containers: Stop all running containers.
##############################################################################
```

このStackScriptでは以下の5つのコマンドが使えるようになっています。

| コマンド | 用途 |
|:--|:--|
| pytorch | PyTorchがインストールされたコンテナを起動してシェルに入る |
| tensorflow | TensorFlowがインストールされたコンテナを起動してシェルに入る |
| pytorch-notebook | PyTorchがインストールされたJupyter Notebookをデーモンとして起動する |
| tensorflow-notebook | TensorFlowがインストールされたJupyter Notebookをデーモンとして起動する |
| stop-all-containers | 起動しているコンテナを全て停止させる |

また、それぞれのコンテナには`/workspace/HOST-VOLUME/`と`/workspace/OBJECT-STORAGE/`というディレクトリが用意されており、ホストマシンのディレクトリと外部Object Storageをマウントしています。上記コマンドで作成されるコンテナは停止時にコンテナのファイルシステムをクリアする設定になっている(`docker run`の`--rm`オプションに相当)ため、作業後に残したいファイルは`/workspace/HOST-VOLUME/`か`/workspace/OBJECT-STORAGE/`に置いてください。
![mount.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/af6fbad5-ca4e-d9fe-91cb-3977b00b4b79.png)
ここでは例としてPyTorchがインストールされたJupyter Notebookをデーモンとして起動し、音声認識モデルである[OpenAI Whisper](https://openai.com/blog/whisper/)を実行してみます。先ほどのコンソールから `pytorch-notebook` コマンドを実行します。

```console
root@139-162-XX-XXX:~# pytorch-notebook
[I 04:36:22.823 NotebookApp] http://hostname:8888/?token=0ee3290287b3bd90f2e8e3ab447965d3e074267f0d60420b
        http://hostname:8888/?token=0ee3290287b3bd90f2e8e3ab447965d3e074267f0d60420b
```

これでJupyter Notebookが起動しました。問題なく上記のような結果になったら、URLのhostnameの部分を、仮想マシン作成時にメモしておいた仮想マシンのIPアドレスで置き換え、:8888を削除してWebブラウザからアクセスします。Tokenはコンテナの起動の度に変わります。

※起動時に「Bind for 0.0.0.0:80 failed: port is already allocated.」というエラーが出た場合は、すでにバックグラウンドで起動しているJupyter Notebookが存在するので`stop-all-containers`コマンドで先にそれを停止させてください。

| コンソールに表示されるURL例 | Webブラウザからのアクセスに使うURL例 |
|:--|:--|
| http://hostname:8888/?token=0ee3290287b3bd90f2e8e3ab447965d3e074267f0d60420b | http://139.162.XX.XX/?token=0ee3290287b3bd90f2e8e3ab447965d3e074267f0d60420b |

`HOST-VOLUME`をクリックし、その中にある`Voice Recognition with OpenAI Whisper.ipynb`をクリックして開きます。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/9442a6de-3a41-e24c-58ba-8bc5413fc426.png)
メニューの`Cell`→`Run All`を選ぶとOpenAI Whisperが実行されます。初回の実行時は関連ソフトウェアやディープラーニングモデルのダウンロードに数分かかります。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/55e20feb-b6f2-c18e-0e81-327fbad58d41.png)
問題なく実行が完了すると最後のセルに「I'm getting them for $12 a night.」と音声認識の結果が表示されます。

**おめでとうございます! これでGPU対応のPyTorchとTensorFlowの準備が整いました!**

# 仮想マシンの削除

使い終わったACCの仮想マシンは、ACCの管理コンソールの右上にあるメニューから「Delete」で削除できます。その際`/workspace/HOST-VOLUME/`(ホストOSから見ると `/root/shared/`)の中身は削除されますので、必要なファイルは別途退避させておいてください。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/22882f25-850d-9945-4874-fdb724cbdf17.png)

:::note warn
ACCでは停止した仮想マシンも課金対象です。課金を止めたい場合は仮想マシンを削除してください
**参考: [Platform - Billing](https://www.linode.com/docs/products/platform/billing/#if-my-linode-is-powered-off-will-i-be-billed)**
:::

# 実運用に向けての考慮点

この記事では説明をシンプルにするために実運用においては配慮すべき点をいくつか割愛しています。実運用に際してはたとえば以下の点を考慮する必要があります。

## アクセス制御

上記の手順で作成した仮想マシンへのSSH経由でのアクセスにはパスワード認証もしくは公開鍵認証、Jupyter Notebookにはトークン認証がかかっていますが、さらにアクセス元IPアドレスでアクセス制限したい場合、以下の記事を参考にポート22 (SSH)と、ポート80 (HTTP)のみがアクセス許可されるようファイアウォールをかけてください。

https://qiita.com/mtsuchih/items/cd4402e96a80e66a4581

さらに高度なアクセス制限をかけたい場合、AkamaiのゼロトラストソリューションであるEnterprise Application Accessを使用することで、外部Identity Providerとの連携、SSO対応などもできます。
[Enterprise Application Access：製品概要](https://www.akamai.com/ja/resources/product-brief/enterprise-application-access-product-brief)

## HTTPSの有効化

Jupyter NotebookはデフォルトでHTTP通信になります。必要に応じて以下の手順でHTTPSを有効化してください。

[Running a public notebook server](https://jupyter-notebook.readthedocs.io/en/stable/public_server.html#notebook-public-server)

上記で紹介している5つの起動コマンドは`/root/.bash_profile`の中でdockerコマンドのエイリアスとして定義されています。HTTPSを有効化する際には`pytorch-notebook`と`tensorflow-notebook`コマンドで使われている`docker`コマンドの`-p`オプションの値も適切なポートに変更し、`ufw allow [ポート番号]/tcp`コマンドでLinuxのファイアウォールがHTTPSのポートを許可するようにしてください。

# 関連記事

アカマイ・テクノロジーズ合同会社のQiitaではACC関連など開発者向けの記事を記載しております。

https://qiita.com/organizations/Akamai