多くのアプリケーション、特にリソースを大量に消費する機械学習 (ML) アプリケーションでは、GPU アクセラレーションを利用できます。 このようなアプリケーションの開発時間は、開発に使用するマシンのハードウェアによって異なる場合があります。 コンテナ化は、再現性のために開発を容易にし、セットアップを他のマシンに簡単に転送できるようにします。 最も重要なことは、コンテナ化されたアプリケーションは、さまざまなハードウェア構成を利用できる Amazon ECS などのプラットフォームに簡単にデプロイできることです。
このチュートリアルでは、コンテナで GPU アクセラレーションアプリケーションをローカルで開発する方法と、Docker Compose を使用してクラウド (Amazon ECS プラットフォーム) に簡単にデプロイする方法について説明します。 ローカル環境からクラウドへの移行を簡単に行い、GPU アクセラレーション アプリケーションはすべての依存関係と共に Docker イメージにパッケージ化され、ターゲット環境に関係なく同じ方法でデプロイされます。
必要条件
このチュートリアルに従うには、次のツールをローカルにインストールする必要があります。
- ウィンドウズとMacOS:Docker Desktopをインストールする
- Linux: Docker Engine と Compose CLIをインストールする
- Amazon ECS にデプロイするには: AWS アカウント
クラウド プラットフォームへのデプロイについては、Docker CLI バイナリに埋め込まれた新しい Docker Compose 実装に依存しています。 したがって、クラウドプラットフォーム docker compose
をターゲットにする場合は、代わりに docker-compose
コマンドを実行します。 ローカル コマンドの場合、Docker Compose の両方の実装が機能するはずです。 使用している不足している機能を見つけた場合は、 課題トラッカーで報告してください。
サンプル アプリケーション
紹介したいのは、Docker Composeを使用してGPUアクセラレーションアプリケーションを構築および管理する方法と、それをクラウドにデプロイする方法であることに注意してください。 GPUプログラミングやAI / MLアルゴリズムに焦点を当てるのではなく、移植性、共有、デプロイを容易にするために、そのようなアプリケーションを構築およびコンテナ化する方法に焦点を当てています。
このチュートリアルでは、Tensorflow ドキュメントで提供されているサンプルコードを使用して、Docker Compose でオーケストレーションできる GPU アクセラレーション翻訳サービスをシミュレートします。 元のコードは、 https://www.tensorflow.org/tutorials/text/nmt_with_attentionに記載されています。 この演習では、Docker Compose で簡単に管理できるようにコードを再編成しました。
このサンプルでは、ホストで使用可能な場合は GPU デバイスを自動的に使用できる Tensorflow プラットフォームを使用します。 次に、このサンプルをサービスで整理して簡単にコンテナー化する方法と、リソースを大量に消費するアプリケーションをローカルで実行する場合の課題について説明します。
手記: このチュートリアル全体で使用するサンプル コードは、 こちらにあります。 これから説明するコマンドを実行するには、ローカルにダウンロードする必要があります。
1. 地域環境
単純な文を選択した言語に翻訳できるサービスを構築してデプロイするとします。 このようなサービスでは、ある言語から別の言語に翻訳するように ML モデルをトレーニングし、このモデルを使用して新しい入力を翻訳する必要があります。
アプリケーションのセットアップ
ML プロセスのフェーズを 2 つの異なる Compose サービスに分離することを選択します。
- 2 つの言語間で翻訳するモデルをトレーニングするトレーニング サービス (実際のトレーニング プロセスの前に、データ収集、前処理、および必要なすべての手順を含む)。
- モデルを読み込み、それを使用して文を「翻訳」する翻訳サービス。
この構造体は、次の内容を持つダウンロードしたサンプル アプリケーションから docker-compose.dev.yaml で定義されています。
docker-compose.yml
services:
training:
build: backend
command: python model.py
volumes:
- models:/checkpoints
translator:
build: backend
volumes:
- models:/checkpoints
ports:
- 5000:5000
volumes:
models:
トレーニング サービスでモデルをトレーニングして英語からフランス語に翻訳し、このモデルを 2 つのサービス間で共有される名前付きボリューム モデル に保存する必要があります。 トランスレーターサービスには、簡単にクエリを実行できるように公開されたポートがあります。
Docker Compose を使用してローカルにデプロイする
簡略化された作成ファイルから始める理由は、GPUが存在するかどうかに関係なく、ローカルに展開できるためです。 GPUリソース予約を追加する方法については、後で説明します。
デプロイする前に、 docker-compose.dev.yaml の名前を docker-compose.yaml に変更して、すべての作成コマンドに対してフラグ -f を使用してファイルパスが設定されないようにします。
Composeファイルをデプロイするには、ターミナルを開き、そのベースディレクトリに移動して、次のコマンドを実行するだけです。
$ docker compose up
The new 'docker compose' command is currently experimental.
To provide feedback or request new features please open
issues at https://github.com/docker/compose-cli
[+] Running 4/0
⠿ Network "gpu_default" Created 0.0s
⠿ Volume "gpu_models" Created 0.0s
⠿ gpu_translator_1 Created 0.0s
⠿ gpu_training_1 Created 0.0s
Attaching to gpu_training_1, gpu_translator_1
...
translator_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C
to quit)
...
HTTP/1.1" 200 -
training_1 | Epoch 1 Batch 0 Loss 3.3540
training_1 | Epoch 1 Batch 100 Loss 1.6044
training_1 | Epoch 1 Batch 200 Loss 1.3441
training_1 | Epoch 1 Batch 300 Loss 1.1679
training_1 | Epoch 1 Loss 1.4679
training_1 | Time taken for 1 epoch 218.06381964683533 sec
training_1 |
training_1 | Epoch 2 Batch 0 Loss 0.9957
training_1 | Epoch 2 Batch 100 Loss 1.0288
training_1 | Epoch 2 Batch 200 Loss 0.8737
training_1 | Epoch 2 Batch 300 Loss 0.8971
training_1 | Epoch 2 Loss 0.9668
training_1 | Time taken for 1 epoch 211.0763041973114 sec
...
training_1 | Checkpoints saved in /checkpoints/eng-fra
training_1 | Requested translator service to reload its model,
response status: 200
translator_1 | 172.22.0.2 - - [18/Dec/2020 10:23:46]
"GET /reload?lang=eng-fra
Docker Composeは、サービスごとにコンテナをデプロイし、そのログに添付して、トレーニングサービスの進行状況を追跡できるようにします。
トレーニング サービスは、10 サイクル (エポック) ごとに、最後のチェックポイントからモデルを再読み込みするようにトランスレーターに要求します。 最初のトレーニングフェーズ(10サイクル)が完了する前に翻訳者にクエリを実行すると、次のメッセージが表示されます。
$ curl -d "text=hello" localhost:5000/
No trained model found / training may be in progress...
ログから、各トレーニングサイクルはリソースを大量に消費し、非常に時間がかかる可能性があることがわかります(MLアルゴリズムのパラメーター設定によって異なります)。
トレーニング サービスは継続的に実行され、2 つのサービス間で共有される名前付きボリュームにモデルを定期的にチェックポイントします。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f11fc947a90a gpu_training "python model.py" 14 minutes ago Up 54 minutes gpu_training_1
baf147fbdf18 gpu_translator "/bin/bash -c 'pytho..." 14 minutes ago Up 54 minutes 0.0.0.0:5000->5000/tcp gpu_translator_1
これで、トレーニング済みのモデルを使用するトランスレーター サービスを照会できます。
$ $ curl -d "text=hello" localhost:5000/
salut !
$ curl -d "text=I want a vacation" localhost:5000/
je veux une autre .
$ curl -d "text=I am a student" localhost:5000/
je suis etudiant .
この演習では、変換の精度ではなく、Docker Compose で簡単にデプロイできるサービスアプローチに従ってプロセス全体を設定する方法に関心があることに注意してください。
開発中は、アルゴリズムを微調整するたびに、トレーニングプロセスを再実行して評価する必要がある場合があります。 これは、高性能用に構築された開発マシンを使用しない場合、非常に時間のかかる作業です。
別の方法は、オンデマンドのクラウドリソースを使用することです。 たとえば、GPU デバイスをホストするクラウドインスタンスを使用して、アプリケーションのリソースを大量に消費するコンポーネントを実行できます。 GPU にアクセスできるマシンでサンプル アプリケーションを実行すると、GPU でモデルをトレーニングするように自動的に切り替わります。 これにより、プロセスがスピードアップし、開発時間が大幅に短縮されます。
このアプリケーションをより高速なクラウド インスタンスにデプロイする最初の手順は、アプリケーションを Docker イメージとしてパックし、クラウド インスタンスからアクセスできる Docker Hub にプッシュすることです。
イメージをビルドして Docker Hub にプッシュする
を使用したデプロイ compose up
中に、アプリケーションは Docker イメージとしてパックされ、コンテナーの作成に使用されます。 ビルドされたイメージにタグを付けて、Docker Hub にプッシュする必要があります。
これを行う簡単な方法は、Composeファイルでサービスのimageプロパティを設定することです。 以前は、サービスの build プロパティのみを設定していましたが、イメージは定義されていませんでした。 Docker Compose では、アプリケーションをデプロイするために、これらのプロパティの少なくとも 1 つを定義する必要があります。
パターン <account>/<name>: に従って画像プロパティを設定します。タグは省略可能です (デフォルトは<tag>
'latest')。たとえば、Docker Hub アカウント ID myhubuser とアプリケーション名 gpudemo を取り上げます。 作成ファイルを編集し、2 つのサービスの image プロパティを次のように設定します。
docker-compose.yml
services:
training:
image: myhubuser/gpudemo
build: backend
command: python model.py
volumes:
- models:/checkpoints
translator:
image: myhubuser/gpudemo
build: backend
volumes:
- models:/checkpoints
ports:
- 5000:5000
volumes:
models:
イメージをビルドするには、次のコマンドを実行します。
$ docker compose build
The new 'docker compose' command is currently experimental. To
provide feedback or request new features please open issues
at https://github.com/docker/compose-cli
[+] Building 1.0s (10/10) FINISHED
=> [internal] load build definition from Dockerfile
0.0s
=> => transferring dockerfile: 206B
...
=> exporting to image
0.8s
=> => exporting layers
0.8s
=> => writing image sha256:b53b564ee0f1986f6a9108b2df0d810f28bfb209
4743d8564f2667066acf3d1f
0.0s
=> => naming to docker.io/myhubuser/gpudemo
$ docker images | grep gpudemo
myhubuser/gpudemo latest b53b564ee0f1 2 minutes ago
5.83GB
画像には、Composeファイルで設定した内容に従って名前が付けられていることに注意してください。
このイメージをDocker Hubにプッシュする前に、ログインしていることを確認する必要があります。 このために、以下を実行します。
$ docker login
...
Login Succeeded
ビルドしたイメージをプッシュします。
$ docker compose push
Pushing training (myhubuser/gpudemo:latest)...
The push refers to repository [docker.io/myhubuser/gpudemo]
c765bf51c513: Pushed
9ccf81c8f6e0: Layer already exists
...
latest: digest: sha256:c40a3ca7388d5f322a23408e06bddf14b7242f9baf7fb
e7201944780a028df76 size: 4306
プッシュされたイメージは、Docker Hub のリポジトリ設定でプライベートに設定しない限り、パブリックです。 Docker のドキュメント では、これについて詳しく説明します。
イメージがパブリックイメージレジストリに保存されているので、それを使用してアプリケーションを Amazon ECS にデプロイする方法と、GPU を使用して高速化する方法を見ていきます。
2. GPU アクセラレーションのために Amazon ECS にデプロイする
アプリケーションを Amazon ECS にデプロイするには、AWS アカウントにアクセスするための認証情報と、プラットフォームをターゲットにするように Docker CLI を設定する必要があります。
AWS のサービスへの接続に使用できる有効な AWS 認証情報のセットがあると仮定しましょう。 次に、すべての Docker CLI コマンドを Amazon ECS にリダイレクトするための ECS Docker コンテキストを作成する必要があります。
ECS コンテキストを作成する
ECS コンテキストを作成するには、次のコマンドを実行します。
$ docker context create ecs cloud
? Create a Docker context using: [Use arrows to move, type
to filter]
> AWS environment variables
An existing AWS profile
A new AWS profile
これにより、AWS 認証情報のセットアップに精通しているかどうかに応じて、3 つのオプションが表示されます。
この演習では、AWS 認証情報のセットアップの詳細をスキップするために、最初のオプションを選択します。 AWS_ACCESS_KEY
これには、Amazon ECS をターゲットとする Docker コマンドを実行するときに、環境で と AWS_SECRET_KEY
を設定する必要があります。
これで、Dockerコマンドを実行して、プラットフォームをターゲットとするすべてのコマンドにコンテキストフラグを設定するか、使用中のコンテキストに切り替えて、各コマンドにフラグを設定しないようにすることができます。
ECS をターゲットにするように Docker CLI を設定する
次のコマンドを実行して、前に作成したコンテキストを使用中のコンテキストとして設定します。
$ docker context use cloud
$ docker context ls
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
cloud * ecs credentials read from environment
ここから、後続のすべての Docker コマンドは Amazon ECS をターゲットにします。 ローカル環境を対象とする既定のコンテキストに戻すには、次のコマンドを実行します。
$ docker context use default
次のコマンドでは、ECS コンテキストを現在のコンテキストとして使用します。 これで、コマンドを実行して、ECSに正常にアクセスできることを確認できます。
$ AWS_ACCESS_KEY="*****" AWS_SECRET_KEY="******" docker compose ls
NAME STATUS
アプリケーションを Amazon ECS にデプロイする前に、トレーニングサービスの GPU アクセスをリクエストするように Compose ファイルを更新する方法を見てみましょう。 この ブログ投稿 では、GPU 予約を定義する方法について説明します。 次のセクションでは、ローカル作成でサポートされている新しい形式と レガシー docker-compose
。
作成ファイルで GPU 予約を定義する
Tensorflow は、CUDA コンピューティング機能を備えた NVIDIA GPU を利用して、計算を高速化できます。 NVIDIA GPU を予約するには、docker-compose.yaml を編集します 前に定義し、 次のようにトレーニング サービスの下にdeployプロパティを追加します。
...
training:
image: myhubuser/gpudemo
command: python model.py eng-fra
volumes:
- models:/checkpoints
deploy:
resources:
reservations:
memory:32Gb
devices:
- driver: nvidia
count: 2
capabilities: [gpu]
...
この例では、コンテナー専用の 2 つの NVIDIA GPU と 32 GB のメモリの予約を定義しました。 これらのパラメーターは、デプロイの対象となるマシンのリソースに応じて調整できます。 ローカルの開発マシンがNVIDIA GPUをホストしている場合は、それに応じて予約を微調整し、作成ファイルをローカルにデプロイできます。 作成ファイルをデプロイする前に、 NVIDIA コンテナー ランタイム がインストールされていることを確認し、それを使用するように Docker エンジンを設定します。
次のパートでは、GPU クラウド インスタンスを使用してサンプル アプリケーションを実行する方法について説明します。
注: Docker Hub にプッシュしたイメージはパブリックであることを前提としています。 その場合、プルするために認証する必要はありません(プルレート制限を超えない限り)。 プライベートにしておく必要があるイメージの場合は、認証に使用する認証情報を参照して x-aws-pull_credentials プロパティを定義する必要があります。 設定方法の詳細については、 ドキュメントを参照してください。
Amazon ECS へのデプロイ
AWS 認証情報をエクスポートして、すべてのコマンドに設定しないようにします。
$ export AWS_ACCESS_KEY="*****"
$ export AWS_SECRET_KEY="******"
作成ファイルをデプロイすると、Docker Compose は、予約パラメータを満たす GPU 機能を備えた EC2 インスタンスも予約します。 この例では、32GBと2つのNvidiaGPUを搭載したインスタンスを予約するように求めています。 Docker Compose は、この予約を、この要件を満たすインスタンスと照合します。 Compose ファイルで予約プロパティを設定する前に、Amazon GPU インスタンスタイプを確認し、それに応じて予約を設定することをお勧めします。 そのようなインスタンスを含むAmazonリージョンをターゲットにしていることを確認してください。
警告:ECSコンテナとは別に、 'g4dn.12xlarge'があります EC2 インスタンスが予約されています。 クラウドにデプロイする前に、Amazon のドキュメントで、これが発生するリソースコストを確認してください。
アプリケーションをデプロイするには、ローカル環境と同じコマンドを実行します。
$ docker compose up
[+] Running 29/29
⠿ gpu CreateComplete 423.0s
⠿ LoadBalancer CreateComplete 152.0s
⠿ ModelsAccessPoint CreateComplete 6.0s
⠿ DefaultNetwork CreateComplete 5.0s
...
⠿ TranslatorService CreateComplete 205.0s
⠿ TrainingService CreateComplete 161.0s
サービスのステータスを確認します。
$ docker compose ps
NAME SERVICE STATE PORTS
task/gpu/3311e295b9954859b4c4576511776593 training Running
task/gpu/78e1d482a70e47549237ada1c20cc04d translator Running gpu-LoadBal-6UL1B4L7OZB1-d2f05c385ceb31e2.elb.eu-west-3.amazonaws.com:5000->5000/tcp
公開されているトランスレーター エンドポイントを照会します。 ローカルデプロイと同じ動作が見られます(モデルのリロードはトレーニングサービスによってまだトリガーされていません)。
$ curl -d "text=hello" gpu-LoadBal-6UL1B4L7OZB1-d2f05c385ceb31e2.elb.eu-west-3.amazonaws.com:5000/
No trained model found / training may be in progress...
検出された GPU デバイスのテンソルフローのログを確認します。 予約した2つのGPUデバイスと、トレーニングがCPUベースのローカルトレーニングよりもほぼ10倍高速であることを簡単に特定できます。
$ docker compose logs
...
training | 2021-01-08 20:50:51.595796: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1720] Found device 0 with properties:
training | pciBusID: 0000:00:1c.0 name: Tesla T4 computeCapability: 7.5
training | coreClock: 1.59GHz coreCount: 40 deviceMemorySize: 14.75GiB deviceMemoryBandwidth: 298.08GiB/s
...
training | 2021-01-08 20:50:51.596743: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1720] Found device 1 with properties:
training | pciBusID: 0000:00:1d.0 name: Tesla T4 computeCapability: 7.5
training | coreClock: 1.59GHz coreCount: 40 deviceMemorySize: 14.75GiB deviceMemoryBandwidth: 298.08GiB/s
...
training | Epoch 1 Batch 300 Loss 1.2269
training | Epoch 1 Loss 1.4794
training | Time taken for 1 epoch 42.98397183418274 sec
...
training | Epoch 2 Loss 0.9750
training | Time taken for 1 epoch 35.13995909690857 sec
...
training | Epoch 9 Batch 0 Loss 0.1375
...
training | Epoch 9 Loss 0.1558
training | Time taken for 1 epoch 32.444278955459595 sec
...
training | Epoch 10 Batch 300 Loss 0.1663
training | Epoch 10 Loss 0.1383
training | Time taken for 1 epoch 35.29659080505371 sec
training | Checkpoints saved in /checkpoints/eng-fra
training | Requested translator service to reload its model, response status: 200.
トレーニング サービスは継続的に実行され、10 サイクル (エポック) ごとに翻訳サービスでモデルのリロードをトリガーします。 翻訳サービスに少なくとも一度通知されると、トレーニングサービスを停止して削除し、いつでもGPUインスタンスをリリースできます。
これは、Composeファイルからサービスを削除することで簡単に実行できます。
services:
translator:
image: myhubuser/gpudemo
build: backend
volumes:
- models:/checkpoints
ports:
- 5000:5000
volumes:
models:
その後、もう一度実行 docker compose up
して、実行中のアプリケーションを更新します。 これにより、変更が適用され、トレーニングサービスが削除されます。
$ docker compose up
[+] Running 0/0
⠋ gpu UpdateInProgress User Initiated
⠋ LoadBalancer CreateComplete
⠋ ModelsAccessPoint CreateComplete
...
⠋ Cluster CreateComplete
⠋ TranslatorService CreateComplete
実行中のサービスを一覧表示して、トレーニングサービスが削除され、翻訳者が1人しかいないことを確認できます。
$ docker compose ps
NAME SERVICE STATE PORTS
task/gpu/78e1d482a70e47549237ada1c20cc04d translator Running gpu-LoadBal-6UL1B4L7OZB1-d2f05c385ceb31e2.elb.eu-west-3.amazonaws.com:5000->5000/tcp
トランスレータを照会します。
$ curl -d "text=hello" gpu-LoadBal-6UL1B4L7OZB1-d2f05c385ceb31e2.elb.eu-west-3.amazonaws.com:5000/
salut !
Amazon ECS からアプリケーションを削除するには、次のコマンドを実行します。
$ docker compose down
概要
リソースを大量に消費する ML アプリケーションを設定して、Docker Compose を使用してさまざまな環境に簡単にデプロイできるようにする方法について説明しました。 作成ファイルで GPU の使用を定義する方法と、それを Amazon ECS にデプロイする方法について説明しました。