T-CREATOR

Docker で GPU を活用する:機械学習環境を構築するための手順

Docker で GPU を活用する:機械学習環境を構築するための手順

機械学習の分野では、大規模なデータセットを扱ったり、複雑な深層学習モデルを訓練したりする際に、GPU の並列処理能力が必要不可欠となります。しかし、GPU を使った機械学習環境の構築は、ドライバーやライブラリの依存関係が複雑で、環境構築に多くの時間を費やしてしまうことも少なくありません。

Docker を使って GPU 対応の機械学習環境を構築することで、これらの課題を大幅に軽減できます。環境の再現性や移植性が向上し、チーム開発や本番環境への展開も格段にスムーズになるでしょう。

背景

GPU コンピューティングとは

GPU(Graphics Processing Unit)は元々グラフィックス処理専用のプロセッサでしたが、現在では汎用的な並列計算処理において CPU を大幅に上回る性能を発揮します。特に機械学習では、行列演算やテンソル計算の並列処理において、その真価を発揮しています。

以下の図は、GPU コンピューティングがどのように機械学習処理を高速化するかを示しています。

mermaidflowchart TD
    data[訓練データ] --> preprocessing[前処理]
    preprocessing --> cpu_path[CPU処理]
    preprocessing --> gpu_path[GPU処理]

    cpu_path --> cpu_calc[順次計算<br/>コア数: 8-16]
    gpu_path --> gpu_calc[並列計算<br/>CUDAコア: 2000-10000+]

    cpu_calc --> cpu_result[訓練時間: 10-24時間]
    gpu_calc --> gpu_result[訓練時間: 30分-2時間]

    cpu_result --> model[学習済みモデル]
    gpu_result --> model

この図からわかるように、GPU の大量の並列処理コアにより、従来 CPU で数時間から数日かかっていた処理を大幅に短縮できます。

従来の CPU 環境との比較

項目CPU 環境GPU 環境
並列処理コア数8-32 コア1000-10000+コア
機械学習タスク処理速度基準値10-100 倍高速
メモリ帯域幅50-100 GB/s500-1500 GB/s
電力効率低い数倍高効率
開発環境セットアップ簡単複雑(従来)

従来の CPU 環境では、深層学習モデルの訓練に非常に長い時間がかかり、研究開発の効率が大幅に制限されていました。GPU を活用することで、より多くの実験を短時間で行え、機械学習プロジェクトの生産性を劇的に向上させることが可能です。

Docker コンテナ技術の基礎

Docker は、アプリケーションとその実行環境を軽量なコンテナとしてパッケージ化する技術です。従来の仮想マシンと比較して、リソース使用量が少なく、起動時間も格段に短縮されています。

Docker の主要な特徴は以下の通りです:

  • 軽量性: ホスト OS のカーネルを共有するため、オーバーヘッドが最小限
  • 移植性: 同じコンテナイメージを異なる環境で実行可能
  • 再現性: Dockerfile によって環境構築手順を明確に定義
  • 分離性: 各コンテナは独立した名前空間を持つ

課題

ホスト GPU への直接アクセス問題

Docker コンテナは基本的にホストシステムから分離された環境で実行されます。そのため、コンテナ内のアプリケーションがホスト GPU に直接アクセスすることは通常できません。

この問題により、以下のような課題が発生していました:

mermaidflowchart LR
    host[ホストシステム<br/>GPU搭載] --> container[Dockerコンテナ]
    container --> app[機械学習アプリ]

    container -.->|アクセス不可| gpu[GPU<br/>NVIDIA/AMD]

    app --> error[GPU not found<br/>エラー発生]

この図が示すように、標準的な Docker 環境では GPU リソースがコンテナから見えないため、GPU を活用した機械学習処理が実行できませんでした。

環境依存による移植性の課題

GPU を使った機械学習環境は、以下のような複数のコンポーネントに依存します:

  1. GPU ドライバー: NVIDIA GPU の場合、CUDA ドライバー
  2. CUDA ツールキット: GPU 計算用のライブラリとランタイム
  3. 機械学習フレームワーク: PyTorch、TensorFlow など
  4. Python 環境: 特定のバージョンの Python と依存パッケージ

これらの依存関係は、異なる環境(開発マシン、本番サーバー、クラウドインスタンス)で一致させることが困難で、「ローカルでは動作するが本番で動かない」といった問題が頻発していました。

リソース管理の複雑さ

複数の機械学習プロジェクトを同時に実行する場合、GPU メモリの競合や CUDA バージョンの不整合などの問題が発生しやすくなります。また、GPU を複数人で共有する場合のリソース分離も困難でした。

解決策

NVIDIA Docker(nvidia-container-toolkit)の概要

NVIDIA Container Toolkit は、Docker コンテナ内から GPU を安全かつ効率的に利用できるようにする公式ツールです。このツールを使用することで、GPU の能力をコンテナ化された環境で完全に活用できます。

NVIDIA Container Toolkit の主な機能は以下の通りです:

  • GPU パススルー: ホスト GPU をコンテナ内で直接使用可能
  • ドライバー自動マッピング: ホストの GPU ドライバーをコンテナに自動マッピング
  • リソース分離: 複数コンテナ間での GPU リソース制御
  • セキュリティ: 安全な GPU アクセス制御機能

GPU パススルー機能

GPU パススルー機能により、Docker コンテナは物理 GPU に直接アクセスできるようになります。以下の図は、この仕組みを示しています。

mermaidsequenceDiagram
    participant App as 機械学習アプリ
    participant Container as Dockerコンテナ
    participant Runtime as nvidia-container-runtime
    participant GPU as ホストGPU

    App->>Container: GPU計算要求
    Container->>Runtime: CUDA API呼び出し
    Runtime->>GPU: GPU命令実行
    GPU->>Runtime: 計算結果
    Runtime->>Container: 結果返却
    Container->>App: 結果取得

この仕組みにより、コンテナ内のアプリケーションは、まるでホスト環境で直接実行されているかのように GPU を活用できます。

コンテナレベルでの GPU リソース管理

Docker の GPU サポートにより、以下のようなリソース管理が可能になります:

  • GPU 割り当て制御: --gpus フラグによる特定 GPU の割り当て
  • GPU メモリ制限: コンテナごとの GPU メモリ使用量制御
  • 複数 GPU 対応: マルチ GPU 環境での効率的な負荷分散

具体例

環境準備(Docker + NVIDIA Driver + CUDA)

まず、GPU 対応の Docker 環境を構築するための前提条件を確認しましょう。

NVIDIA GPU ドライバーの確認

システムに NVIDIA GPU ドライバーがインストールされているかを確認します。

bashnvidia-smi

このコマンドが正常に実行され、GPU 情報が表示されれば、ドライバーは正しくインストールされています。

bash# 期待される出力例
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.85.12    Driver Version: 525.85.12    CUDA Version: 12.0  |
|-------------------------------+----------------------+----------------------+
| 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 RTX 4080    Off  | 00000000:01:00.0 On |                  N/A |
| 30%   45C    P8    25W / 320W|   1024MiB / 16376MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

Docker のインストール

Docker がインストールされていない場合は、公式サイトから最新版をインストールします。

bash# Ubuntu/Debian の場合
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# ユーザーをdockerグループに追加
sudo usermod -aG docker $USER

NVIDIA Container Toolkit のインストール

GPU 対応のために NVIDIA Container Toolkit をインストールします。

bash# GPGキーとリポジトリの追加
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
bash# パッケージの更新とインストール
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

# Dockerサービスの再起動
sudo systemctl restart docker

Docker Compose による機械学習環境構築

実際の機械学習プロジェクトで使用する、本格的な Docker Compose 設定を作成します。

docker-compose.yml の作成

yamlversion: '3.8'

services:
  ml-workspace:
    build:
      context: .
      dockerfile: Dockerfile.gpu
    container_name: ml-gpu-workspace
    ports:
      - '8888:8888' # Jupyter Notebook
      - '6006:6006' # TensorBoard
    volumes:
      - ./data:/workspace/data
      - ./models:/workspace/models
      - ./notebooks:/workspace/notebooks
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    environment:
      - JUPYTER_ENABLE_LAB=yes
      - NVIDIA_VISIBLE_DEVICES=all
    stdin_open: true
    tty: true

Dockerfile.gpu の作成

PyTorch と TensorFlow の両方に対応した、包括的な機械学習環境を構築する Dockerfile です。

dockerfile# NVIDIA公式のCUDA対応Pythonベースイメージを使用
FROM nvidia/cuda:11.8-devel-ubuntu20.04

# 環境変数の設定
ENV DEBIAN_FRONTEND=noninteractive
ENV PYTHONUNBUFFERED=1
ENV CUDA_HOME=/usr/local/cuda
ENV PATH=$CUDA_HOME/bin:$PATH
ENV LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
dockerfile# システムパッケージの更新とインストール
RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    python3-dev \
    build-essential \
    git \
    wget \
    curl \
    vim \
    htop \
    && rm -rf /var/lib/apt/lists/*
dockerfile# Python環境の設定
RUN ln -s /usr/bin/python3 /usr/bin/python

# 基本的なPythonパッケージのインストール
RUN pip install --upgrade pip setuptools wheel

# 機械学習フレームワークのインストール
RUN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
RUN pip install tensorflow[and-cuda]
dockerfile# データサイエンス用パッケージのインストール
RUN pip install \
    jupyter \
    jupyterlab \
    numpy \
    pandas \
    matplotlib \
    seaborn \
    scikit-learn \
    plotly \
    tensorboard \
    wandb

# 作業ディレクトリの設定
WORKDIR /workspace

# Jupyter Labの設定
RUN jupyter lab --generate-config
RUN echo "c.ServerApp.ip = '0.0.0.0'" >> ~/.jupyter/jupyter_lab_config.py
RUN echo "c.ServerApp.allow_root = True" >> ~/.jupyter/jupyter_lab_config.py
RUN echo "c.ServerApp.token = ''" >> ~/.jupyter/jupyter_lab_config.py

# ポートの公開
EXPOSE 8888 6006

# 起動コマンド
CMD ["jupyter", "lab", "--port=8888", "--no-browser", "--allow-root"]

PyTorch/TensorFlow での GPU 動作確認

構築した環境で GPU が正しく認識され、実際に機械学習フレームワークから利用できることを確認します。

環境の起動

bash# Docker Composeを使って環境を起動
docker-compose up -d

# ログを確認してJupyter Labが正常に起動していることを確認
docker-compose logs ml-workspace

PyTorch での GPU 確認コード

コンテナ内で PyTorch から GPU が利用できることを確認します。

pythonimport torch

# GPU が利用可能かチェック
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"CUDA device count: {torch.cuda.device_count()}")

if torch.cuda.is_available():
    # GPU 情報の詳細表示
    print(f"Current GPU: {torch.cuda.get_device_name(0)}")
    print(f"CUDA version: {torch.version.cuda}")

    # GPU メモリ情報
    print(f"GPU memory allocated: {torch.cuda.memory_allocated(0) / 1024**3:.2f} GB")
    print(f"GPU memory cached: {torch.cuda.memory_reserved(0) / 1024**3:.2f} GB")

簡単な GPU 計算テスト

実際に GPU 上でテンソル計算を実行してみます。

pythonimport torch
import time

# CPU と GPU でのテンソル計算速度比較
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")

# 大きなテンソルを作成(1000x1000の行列)
size = 5000
a = torch.randn(size, size).to(device)
b = torch.randn(size, size).to(device)

# GPU計算の実行時間測定
start_time = time.time()
c = torch.mm(a, b)  # 行列の乗算
torch.cuda.synchronize()  # GPU計算の完了を待機
end_time = time.time()

print(f"Matrix multiplication ({size}x{size}): {end_time - start_time:.4f} seconds")

TensorFlow での GPU 確認コード

TensorFlow でも GPU 動作を確認します。

pythonimport tensorflow as tf

# GPU デバイスの確認
print("TensorFlow version:", tf.__version__)
print("GPU devices:", tf.config.experimental.list_physical_devices('GPU'))

# GPU メモリ使用量の制限設定(推奨)
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
    try:
        for gpu in gpus:
            tf.config.experimental.set_memory_growth(gpu, True)
        print(f"GPU memory growth enabled for {len(gpus)} GPU(s)")
    except RuntimeError as e:
        print(f"GPU configuration error: {e}")

実践的な機械学習サンプル

簡単な画像分類モデルを使って、GPU 環境での実際の機械学習処理を体験してみましょう。

pythonimport torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# デバイスの設定
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Training on: {device}")

# データの前処理
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])
python# シンプルなCNNモデル
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(9216, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = nn.functional.relu(x)
        x = self.conv2(x)
        x = nn.functional.relu(x)
        x = nn.functional.max_pool2d(x, 2)
        x = self.dropout1(x)
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        x = nn.functional.relu(x)
        x = self.dropout2(x)
        x = self.fc2(x)
        return nn.functional.log_softmax(x, dim=1)
python# モデルのGPUへの移動と训练
model = SimpleCNN().to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

# GPU上での訓練ループの例
def train_epoch(model, dataloader, optimizer, criterion, device):
    model.train()
    total_loss = 0

    for batch_idx, (data, target) in enumerate(dataloader):
        # データをGPUに移動
        data, target = data.to(device), target.to(device)

        # 勾配をリセット
        optimizer.zero_grad()

        # 順伝播
        output = model(data)
        loss = criterion(output, target)

        # 逆伝播と最適化
        loss.backward()
        optimizer.step()

        total_loss += loss.item()

        if batch_idx % 100 == 0:
            print(f'Batch {batch_idx}, Loss: {loss.item():.6f}')

    return total_loss / len(dataloader)

高度な設定オプション

GPU リソースの細かい制御

Docker Compose で GPU リソースをより詳細に制御することも可能です。

yaml# docker-compose.advanced.yml
version: '3.8'

services:
  ml-training:
    image: pytorch/pytorch:latest
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              device_ids: ['0'] # 特定のGPU IDを指定
              capabilities: [gpu]
    environment:
      - CUDA_VISIBLE_DEVICES=0
      - NVIDIA_VISIBLE_DEVICES=0

  ml-inference:
    image: tensorflow/tensorflow:latest-gpu
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              device_ids: ['1'] # 異なるGPUを割り当て
              capabilities: [gpu]
    environment:
      - CUDA_VISIBLE_DEVICES=1
      - NVIDIA_VISIBLE_DEVICES=1

GPU メモリ監視とデバッグ

GPU 使用状況の監視とトラブルシューティングのためのツールも活用しましょう。

python# GPU メモリ使用量の監視コード
import torch
import psutil

def monitor_gpu_memory():
    if torch.cuda.is_available():
        # 現在のGPUメモリ使用量
        allocated = torch.cuda.memory_allocated(0)
        reserved = torch.cuda.memory_reserved(0)

        print(f"GPU Memory - Allocated: {allocated / 1024**3:.2f} GB")
        print(f"GPU Memory - Reserved: {reserved / 1024**3:.2f} GB")

        # GPU使用率の取得
        import subprocess
        result = subprocess.run(['nvidia-smi', '--query-gpu=utilization.gpu', '--format=csv,noheader,nounits'],
                              capture_output=True, text=True)
        if result.returncode == 0:
            gpu_util = result.stdout.strip()
            print(f"GPU Utilization: {gpu_util}%")

# 使用例
monitor_gpu_memory()

本格的な開発環境の構築

実際のプロジェクト開発で使用できる、より実践的な環境構築例をご紹介します。

プロジェクト構造

arduinoml-project/
├── docker-compose.yml
├── Dockerfile.gpu
├── requirements.txt
├── data/
├── models/
├── notebooks/
├── src/
│   ├── train.py
│   └── inference.py
└── config/
    └── training_config.yaml

本番運用を考慮した Dockerfile

dockerfile# マルチステージビルドでイメージサイズを最適化
FROM nvidia/cuda:11.8-devel-ubuntu20.04 as builder

# 依存関係のインストール(ビルドステージ)
RUN apt-get update && apt-get install -y \
    python3-dev \
    python3-pip \
    build-essential

# Python依存関係のインストール
COPY requirements.txt .
RUN pip install --user -r requirements.txt

# 本番ステージ
FROM nvidia/cuda:11.8-runtime-ubuntu20.04

# 必要最小限のパッケージのみインストール
RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*

# ビルドステージからPythonパッケージをコピー
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH

# アプリケーションコードのコピー
COPY src/ /workspace/src/
COPY config/ /workspace/config/

WORKDIR /workspace

# ヘルスチェックの追加
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s \
  CMD python3 -c "import torch; print('GPU available:', torch.cuda.is_available())"

# デフォルトコマンド
CMD ["python3", "src/train.py"]

開発用の便利なスクリプト

bash#!/bin/bash
# scripts/start-dev.sh

# 開発環境の起動スクリプト
echo "Starting ML GPU development environment..."

# GPU の状態確認
nvidia-smi

# Docker Compose で環境を起動
docker-compose -f docker-compose.yml up -d

# 起動完了の確認
echo "Waiting for services to be ready..."
sleep 10

# Jupyter Lab の URL を表示
echo "Jupyter Lab is available at: http://localhost:8888"

# コンテナの状態確認
docker-compose ps

まとめ

Docker を活用した GPU 対応機械学習環境の構築により、以下のような大きなメリットを得ることができます。

まず、環境構築の簡素化です。複雑な CUDA ドライバーやライブラリの依存関係を Docker イメージに封じ込めることで、「誰でも、どこでも、同じ環境で」機械学習開発を始められます。

次に、開発効率の向上があります。一度構築した環境はチームメンバー間で共有でき、新しいメンバーでも数分で開発環境を準備できるでしょう。また、異なるプロジェクトで異なるバージョンの フレームワークを使い分けることも容易になります。

さらに、本番環境への展開の安全性も向上します。開発環境と本番環境で同一のコンテナイメージを使用することで、「ローカルでは動くが本番で動かない」といった問題を大幅に減らせます。

最後に、リソース管理の最適化により、複数の機械学習プロジェクトを効率的に並行実行できるようになります。GPU リソースの分離や制限により、安定した開発環境を維持できるでしょう。

Docker での GPU 活用は、現代の機械学習開発において必須の技術となっています。本記事の手順を参考に、ぜひ効率的な機械学習環境を構築してください。

関連リンク