Docker/Ubuntu 24.04 + CUDA/GPU 開発環境構築ガイド: WSL2対応とJupyter/PyTorch

Docker コンテナの起動と基本設定

Ubuntu 24.04 コンテナの起動(特権モード)

目的: FUSE デバイスと GUI アプリケーションを使用可能にする。

メリット: ファイルシステム機能と画面表示が利用できる。

docker stop ubuntu
docker rm ubuntu
docker run --cap-add=SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined -e DISPLAY=host.docker.internal:0.0 -it --name ubuntu ubuntu:24.04 /bin/bash

オプション説明:

注意: セキュリティ制約を緩和するため、開発環境または学習環境に限定すること。

コンテナの再開

docker start ubuntu && docker exec -it ubuntu /bin/bash

停止したコンテナを起動し、bash シェルで接続する。コンテナ内のファイルと設定は保持される。

sudo のインストール

目的: Docker コンテナで sudo コマンドを使用可能にする。Ubuntu 公式コンテナイメージには sudo が含まれていない。

if [ -f /.dockerenv ]; then
    if ! command -v sudo &> /dev/null; then
        apt-get update && apt-get install -y sudo
        which sudo > /dev/null 2>&1 || { echo "sudo installation failed"; exit 1; }
    fi
fi

Docker コンテナ内でのみ実行され、sudo が存在しない場合のみインストールする。インストール失敗時はエラーメッセージを表示してスクリプトを終了する。

環境変数の設定

目的: システム全体で使用する設定を /etc/environment に登録する。

echo 'PATH=/opt/conda/bin:$PATH' | sudo tee -a /etc/environment
echo 'SHELL=/bin/bash' | sudo tee -a /etc/environment
echo 'TZ=Asia/Tokyo' | sudo tee -a /etc/environment
source /etc/environment

タイムゾーンの設定

目的: システムのタイムゾーンを Asia/Tokyo に設定する。

sudo apt-get install -y apt-utils debconf && \
sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
echo "Asia/Tokyo" | sudo tee /etc/timezone && \
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata && \
sudo dpkg-reconfigure -f noninteractive tzdata

DEBIAN_FRONTEND=noninteractive により、対話的なプロンプトを表示せずにインストールする。


完全な開発環境の構築手順

Ubuntu 24.04 コンテナの起動(標準モード)

目的: セキュリティ制約を維持した標準的なコンテナを起動する。

メリット: より安全な実行環境となる。

docker stop ubuntu
docker rm ubuntu
docker run --name ubuntu -it ubuntu:24.04 /bin/bash

特別な機能が必要な場合

docker run --cap-add=SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --name ubuntu -it ubuntu:24.04 /bin/bash

環境変数の設定

echo 'PATH=/opt/conda/bin:$PATH' | sudo tee -a /etc/environment
echo 'SHELL=/bin/bash' | sudo tee -a /etc/environment
echo 'TZ=Asia/Tokyo' | sudo tee -a /etc/environment
source /etc/environment

sudo のインストール

if [ -f /.dockerenv ]; then
    if ! command -v sudo &> /dev/null; then
        apt-get update && apt-get install -y sudo
        which sudo > /dev/null 2>&1 || { echo "sudo installation failed"; exit 1; }
    fi
fi

システムの更新

目的: パッケージを最新版に更新し、セキュリティパッチを適用する。

sudo apt-get update && sudo apt-get upgrade -y

タイムゾーンの設定

sudo apt-get install -y apt-utils debconf && \
sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
echo "Asia/Tokyo" | sudo tee /etc/timezone && \
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata && \
sudo dpkg-reconfigure -f noninteractive tzdata

基本パッケージのインストール

目的: Python 開発環境、ビルドツール、バージョン管理システムをインストールする。

sudo apt-get install -y python3 python3-pip python3-dev wget curl git cmake gnupg software-properties-common build-essential

パッケージの役割:

Miniconda3 のインストール

目的: Python 環境管理システムをインストールする。

メリット: システム Python と独立した環境を構築でき、パッケージのバージョン管理が容易になる。

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
    sudo bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/conda && \
    rm Miniconda3-latest-Linux-x86_64.sh

conda の初期設定

目的: bash シェルで conda コマンドを使用可能にし、開発環境を自動アクティベートする。

/opt/conda/bin/conda init bash
echo ". /opt/conda/etc/profile.d/conda.sh" | tee -a ~/.bashrc ~/.bash_profile
echo "conda activate dev" | tee -a ~/.bashrc ~/.bash_profile
source ~/.bashrc || source ~/.bash_profile
grep -q ". /opt/conda/etc/profile.d/conda.sh" ~/.bashrc || echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc

開発環境の作成

目的: Python 3.12 を使用する仮想環境を作成し、科学技術計算とデータ分析に必要なパッケージをインストールする。

conda create -n dev python=3.12 -y
conda install -n dev -y numpy pandas matplotlib scikit-learn jupyter pylint pytest black
grep -q "conda activate dev" ~/.bashrc || echo "conda activate dev" >> ~/.bashrc
conda activate dev

インストールされるパッケージ:

Jupyter Notebook の設定

目的: Jupyter Notebook をネットワーク経由で利用可能にする。

mkdir -p ~/.jupyter && \
    /opt/conda/envs/dev/bin/jupyter notebook --generate-config && \
    echo "c.NotebookApp.ip = '*'" >> ~/.jupyter/jupyter_notebook_config.py && \
    echo "c.NotebookApp.port = 8888" >> ~/.jupyter/jupyter_notebook_config.py && \
    echo "c.NotebookApp.allow_root = True" >> ~/.jupyter/jupyter_notebook_config.py

設定内容:

セキュリティ注意: ip = '*' の設定はセキュリティリスクがある。本番環境では適切なアクセス制御を設定すること。パスワードまたはトークン認証の設定を推奨する。

ファイアウォールのインストール(物理マシンのみ)

目的: UFW をインストールしてネットワークセキュリティを向上させる。

注意: Docker コンテナ内では実行しない(ネットワーク設定との競合を防ぐため)。

if [ ! -f /.dockerenv ]; then
    sudo apt-get -y install ufw
    sudo ufw enable
fi

推奨ドライバのインストール(物理マシンのみ)

目的: Ubuntu が推奨するハードウェアドライバを自動検出してインストールする。NVIDIA GPU ドライバの検出に使用する。

注意: Docker コンテナ内ではホストのドライバを使用するため実行不要。

if [ ! -f /.dockerenv ]; then
    sudo apt install -y ubuntu-drivers-common
    sudo ubuntu-drivers autoinstall
    if ubuntu-drivers devices 2>/dev/null | grep -i nvidia > /dev/null; then
        echo "NVIDIA GPU detected by ubuntu-drivers"
        export ISNVIDIAGPU=True
    else
        echo "No NVIDIA GPU recognized by ubuntu-drivers"
        export ISNVIDIAGPU=False
    fi
fi

CUDA と cuDNN のインストール

目的: NVIDIA GPU で計算処理を実行するためのツールをインストールする。

メリット: GPU を使用した機械学習や科学技術計算の処理速度が大幅に向上する。

sudo apt-get update
sudo apt-get install -y nvidia-cuda-toolkit nvidia-cudnn

NCCL と画像処理ライブラリのインストール

目的: 複数 GPU 間の通信を最適化し、画像処理を高速化する。

メリット: マルチ GPU での分散学習時に通信の負荷を軽減できる。

sudo add-apt-repository -y ppa:graphics-drivers/ppa
sudo apt-get update
sudo apt-get install -y libnccl2 libnccl-dev libnvjpeg-dev

GPU 性能最適化のための環境変数設定

目的: CUDA の動作を最適化する。

export CUDA_DEVICE_ORDER=PCI_BUS_ID
export CUDA_CACHE_DISABLE=0
export CUDA_AUTO_BOOST=1
export CUDA_MODULE_LOADING=LAZY
echo "export CUDA_DEVICE_ORDER=PCI_BUS_ID" >> ~/.bashrc
echo "export CUDA_CACHE_DISABLE=0" >> ~/.bashrc
echo "export CUDA_AUTO_BOOST=1" >> ~/.bashrc
echo "export CUDA_MODULE_LOADING=LAZY" >> ~/.bashrc

環境変数の役割:

CUDA バージョンの取得

目的: インストールされている CUDA のバージョンを検出する。

if command -v nvcc &> /dev/null; then
    CUDAVER=$(nvcc --version | grep "release" | awk '{print $6}' | tr -d ',' | tr -d '.')
    echo "Detected CUDA Version: $CUDAVER"
else
    echo "nvcc not found, assuming no CUDA support."
    CUDAVER="CPU"
fi

バージョン番号から記号を削除する(例: 12.2 → 122)。nvcc が見つからない場合は CPU 版として扱う。

PyTorch のインストール

目的: 検出された CUDA バージョンに対応する PyTorch をインストールする。

メリット: CUDA バージョンの不一致による実行時エラーを防止できる。

if [[ "$CUDAVER" =~ ^[0-9]+$ ]]; then
    echo "Attempting to install PyTorch for CUDA $CUDAVER"

    python3 -m pip install --no-cache-dir torch
    AVAILABLE_CUDA=$(python3 -c "import torch; print(torch.version.cuda.replace('.', '')) if torch.cuda.is_available() else 'CPU'")

    if [[ "$AVAILABLE_CUDA" =~ ^[0-9]+$ ]]; then
        echo "Detected compatible PyTorch CUDA version: $AVAILABLE_CUDA"
        python3 -m pip install --no-cache-dir torch torchvision torchaudio --index-url "https://download.pytorch.org/whl/cu$AVAILABLE_CUDA"
    else
        echo "No compatible CUDA version detected. Installing CPU version."
        python3 -m pip install --no-cache-dir torch torchvision torchaudio
    fi
else
    echo "No valid CUDA version detected. Installing CPU version of PyTorch."
    python3 -m pip install --no-cache-dir torch torchvision torchaudio
fi

まず仮の torch をインストールし、PyTorch が認識する CUDA バージョンを確認する。互換性のあるバージョンが見つかれば GPU 版を、見つからなければ CPU 版をインストールする。--no-cache-dir により pip キャッシュを使用せずディスク容量を節約する。

追加ライブラリのインストール

目的: データ処理とシステムモニタリング用のライブラリをインストールする。

python3 -m pip install --no-cache-dir numpy pandas matplotlib seaborn
python3 -m pip install --no-cache-dir psutil

ディストリビューション情報の取得

目的: OS のディストリビューション情報を取得する。

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
echo "distribution:"
echo $distribution

ディストリビューション名とバージョン番号を連結して表示する(例: ubuntu24.04)。

Jupyter Notebook 起動テスト

目的: Jupyter Notebook が正常に起動するか確認する。

/opt/conda/envs/dev/bin/jupyter notebook --ip=* --port=8888

注意: 起動後、ターミナルに表示される URL とトークンを使用してブラウザからアクセスする。


Windows 環境での WSL2 と Docker を使用した GPU 性能比較

前提条件

次の環境が整っていることを確認する。

Docker Desktop の設定

WSL2 統合の有効化

目的: WSL2 から Docker コマンドを実行可能にする。

手順:

  1. Docker Desktop を開く
  2. 「設定」 > 「リソース」 > 「WSL 統合」を選択
  3. 使用する WSL2 ディストリビューション(例: Ubuntu-24.04)を有効化
  4. 「Apply & Restart」をクリック

GPU サポートの有効化

目的: Docker Engine に NVIDIA Container Runtime を追加し、コンテナ内から GPU を利用可能にする。

Docker Desktop の「設定」 > 「Docker Engine」で、次の JSON 設定を追加する。

{
  "features": {"buildkit": true},
  "experimental": true,
  "runtimes": {
    "nvidia": {
      "path": "nvidia-container-runtime",
      "runtimeArgs": []
    }
  }
}

設定の意味:

設定後、「Apply & Restart」をクリックして Docker を再起動する。

GPU アクセスの確認

目的: Docker コンテナ内から GPU が正常に認識されるか確認する。

docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu24.04 nvidia-smi

オプション説明:

注意: このコマンドが失敗する場合、NVIDIA ドライバまたは Docker の GPU 設定に問題がある。

CUDA 環境確認スクリプトの作成

目的: CUDA と関連ライブラリが正しく設定されているか確認する。

cat > ~/cuda-check.sh << 'EOL'
#!/bin/bash

echo "==== NVIDIA GPU / CUDA / cuDNN 環境チェック ===="

echo -e "\n1. GPU ドライバーチェック"
if command -v nvidia-smi &> /dev/null; then
    nvidia-smi
    echo -e "\nGPU 詳細情報:"
    nvidia-smi -q | grep "Product Name\|CUDA Version\|Driver Version"
else
    echo "エラー: nvidia-smi が見つかりません。"
fi

echo -e "\n2. CUDA 環境チェック"
if command -v nvcc &> /dev/null; then
    nvcc --version
else
    echo "エラー: nvcc が見つかりません。"
fi

echo -e "\n3. cuDNN 確認"
if [ -f /usr/include/cudnn.h ]; then
    grep CUDNN_MAJOR -A 2 /usr/include/cudnn.h
elif [ -f /usr/local/cuda/include/cudnn.h ]; then
    grep CUDNN_MAJOR -A 2 /usr/local/cuda/include/cudnn.h
else
    echo "エラー: cudnn.h が見つかりません。"
fi

echo -e "\n4. パス設定確認"
echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
echo "PATH: $PATH"

echo -e "\n5. システム情報"
uname -a
lscpu | grep "Model name"
free -h
EOL

chmod +x ~/cuda-check.sh
~/cuda-check.sh

nvidia-smi、nvcc、cuDNN の存在確認を順次実行する。環境変数とシステム情報を表示する。chmod +x でスクリプトに実行権限を付与する。

Dockerfile の作成

目的: GPU 対応の Ubuntu 24.04 環境を構築し、PyTorch と GPU 最適化ライブラリをインストールする。

cat > Dockerfile << 'EOF'
FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Tokyo

RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    python3-dev \
    curl \
    git \
    wget \
    gnupg \
    software-properties-common \
    && rm -rf /var/lib/apt/lists/*

RUN curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/3bf863cc.pub | gpg --dearmor -o /usr/share/keyrings/nvidia-archive-keyring.gpg
RUN echo "deb [signed-by=/usr/share/keyrings/nvidia-archive-keyring.gpg] https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/ /" > /etc/apt/sources.list.d/nvidia-cuda.list

RUN apt-get update && apt-get install -y \
    cuda-toolkit-12-2 \
    && rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y \
    libcudnn8 \
    libcudnn8-dev \
    && rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y \
    libnccl2 \
    libnccl-dev \
    && rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y \
    libnvjpeg-dev \
    && rm -rf /var/lib/apt/lists/*

ENV PATH=/usr/local/cuda/bin:${PATH}
ENV LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH}
ENV CUDA_DEVICE_ORDER=PCI_BUS_ID
ENV CUDA_CACHE_DISABLE=0
ENV CUDA_AUTO_BOOST=1
ENV CUDA_MODULE_LOADING=LAZY

RUN pip3 install --no-cache-dir -U pip
RUN pip3 install --no-cache-dir torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

RUN pip3 install --no-cache-dir numpy pandas matplotlib seaborn
RUN pip3 install --no-cache-dir psutil

WORKDIR /app

COPY . /app/
EOF

NVIDIA の公式リポジトリから CUDA Toolkit 12.2 をインストールする。cuDNN、NCCL、NVJPEG ライブラリを追加する。GPU 最適化のための環境変数を設定する。CUDA 12.1 対応の PyTorch をインストールする。

注意: rm -rf /var/lib/apt/lists/* で apt キャッシュを削除し、イメージサイズを削減している。

GPU-CPU 性能比較スクリプトの作成

目的: 行列演算、ニューラルネットワーク、畳み込み等の操作を CPU と GPU で実行し、性能差を測定する。

メリット: CPU と GPU の性能差を定量的に把握できる。GPU 利用の効果を客観的に評価できる。

cat > gpu_cpu_comparison.py << 'EOF'
import torch
import time
import numpy as np

def compare_performance(operation_name, operation_fn, sizes, iterations=10, warmup_iterations=3):
    """
    CPU と GPU で計算性能を比較する。

    Args:
        operation_name: 操作の名前
        operation_fn: 実行する操作の関数
        sizes: テストする入力サイズのリスト
        iterations: 各テストの実行回数
        warmup_iterations: ウォームアップ実行の回数
    """
    print(f"\n===== {operation_name} の性能比較 =====")

    if torch.cuda.is_available():
        print(f"GPU 情報: {torch.cuda.get_device_name()}")
        device_gpu = torch.device("cuda")

        torch.cuda.empty_cache()
        gpu_mem_alloc_start = torch.cuda.memory_allocated(0)
        print(f"初期 GPU 使用メモリ: {gpu_mem_alloc_start / 1024 / 1024:.2f} MB")
    else:
        print("警告: GPU が利用できません。CPU のみで実行します。")
        device_gpu = None

    device_cpu = torch.device("cpu")
    results = []

    for size in sizes:
        print(f"\nサイズ: {size}")

        # ウォームアップ実行
        for i in range(warmup_iterations):
            operation_fn(size, device_cpu)

        # CPU での実行時間測定
        cpu_times = []
        for i in range(iterations):
            torch.cuda.synchronize() if torch.cuda.is_available() else None
            start_time = time.time()
            result = operation_fn(size, device_cpu)
            torch.cuda.synchronize() if torch.cuda.is_available() else None
            end_time = time.time()
            cpu_times.append(end_time - start_time)

        avg_cpu_time = sum(cpu_times) / len(cpu_times)
        std_cpu_time = np.std(cpu_times)
        print(f"CPU 平均実行時間: {avg_cpu_time:.6f} 秒 (標準偏差: {std_cpu_time:.6f})")

        # GPU での実行時間測定
        gpu_times = []
        avg_gpu_time = None
        std_gpu_time = None
        speedup = None
        gpu_mem_used = None

        if device_gpu is not None:
            torch.cuda.empty_cache()

            # ウォームアップ実行
            for i in range(warmup_iterations):
                operation_fn(size, device_gpu)

            gpu_mem_alloc_before = torch.cuda.memory_allocated(0)

            # 実際の計測
            for i in range(iterations):
                torch.cuda.synchronize()
                start_time = time.time()
                result = operation_fn(size, device_gpu)
                torch.cuda.synchronize()
                end_time = time.time()
                gpu_times.append(end_time - start_time)

            gpu_mem_alloc_after = torch.cuda.memory_allocated(0)
            gpu_mem_used = (gpu_mem_alloc_after - gpu_mem_alloc_before) / 1024 / 1024

            avg_gpu_time = sum(gpu_times) / len(gpu_times)
            std_gpu_time = np.std(gpu_times)
            print(f"GPU 平均実行時間: {avg_gpu_time:.6f} 秒 (標準偏差: {std_gpu_time:.6f})")
            print(f"GPU メモリ使用量: {gpu_mem_used:.2f} MB")

            speedup = avg_cpu_time / avg_gpu_time
            print(f"速度向上率 (CPU 時間/GPU 時間): {speedup:.2f}倍")

        results.append({
            "操作": operation_name,
            "サイズ": size,
            "CPU 時間(秒)": avg_cpu_time,
            "CPU 標準偏差": std_cpu_time,
            "GPU 時間(秒)": avg_gpu_time,
            "GPU 標準偏差": std_gpu_time,
            "速度向上率": speedup,
            "GPU メモリ使用(MB)": gpu_mem_used
        })

    return results

def matrix_multiplication(size, device):
    """行列の乗算操作 (FP32)"""
    matrix1 = torch.randn(size, size, device=device)
    matrix2 = torch.randn(size, size, device=device)
    result = torch.matmul(matrix1, matrix2)
    return result

def matrix_multiplication_fp16(size, device):
    """行列の乗算操作 (FP16)"""
    if device.type == "cuda":
        matrix1 = torch.randn(size, size, dtype=torch.float16, device=device)
        matrix2 = torch.randn(size, size, dtype=torch.float16, device=device)
        result = torch.matmul(matrix1, matrix2)
    else:
        matrix1 = torch.randn(size, size, device=device)
        matrix2 = torch.randn(size, size, device=device)
        result = torch.matmul(matrix1, matrix2)
    return result

def matrix_addition(size, device):
    """行列の加算操作"""
    matrix1 = torch.randn(size, size, device=device)
    matrix2 = torch.randn(size, size, device=device)
    result = matrix1 + matrix2
    return result

def neural_network_forward(size, device):
    """ニューラルネットワークの順伝播"""
    model = torch.nn.Sequential(
        torch.nn.Linear(size, size * 2),
        torch.nn.ReLU(),
        torch.nn.Linear(size * 2, size)
    ).to(device)

    input_data = torch.randn(100, size, device=device)
    output = model(input_data)
    return output

def convolution_operation(size, device):
    """畳み込み操作"""
    input_data = torch.randn(10, 3, size, size, device=device)

    conv_layer = torch.nn.Conv2d(
        in_channels=3,
        out_channels=16,
        kernel_size=3,
        padding=1
    ).to(device)

    output = conv_layer(input_data)
    return output

def batch_matrix_multiplication(size, device):
    """バッチ行列乗算"""
    batch_size = 32
    matrix1 = torch.randn(batch_size, size, size, device=device)
    matrix2 = torch.randn(batch_size, size, size, device=device)
    result = torch.bmm(matrix1, matrix2)
    return result

if __name__ == "__main__":
    print("==== GPU 対 CPU 性能比較テスト ====")
    print("PyTorch バージョン:", torch.__version__)
    print("CUDA 利用可能:", torch.cuda.is_available())

    if torch.cuda.is_available():
        print("CUDA バージョン:", torch.version.cuda)
        for i in range(torch.cuda.device_count()):
            print(f"GPU {i}: {torch.cuda.get_device_name(i)}")
            print(f"GPU {i} メモリ総量: {torch.cuda.get_device_properties(i).total_memory / 1024 / 1024 / 1024:.2f} GB")

        print(f"cuDNN バージョン: {torch.backends.cudnn.version()}")
        print(f"cuDNN enabled: {torch.backends.cudnn.enabled}")

        torch.backends.cudnn.enabled = True
        torch.backends.cudnn.benchmark = True
        print("\ncuDNN benchmark モードを有効化しました")
    else:
        print("警告: GPU が検出されませんでした。ドライバーと CUDA の設定を確認してください。")

    print("\n==== システム情報 ====")
    import platform
    import psutil
    print(f"OS: {platform.platform()}")
    print(f"Python: {platform.python_version()}")
    print(f"CPU: {platform.processor()}")
    print(f"物理コア数: {psutil.cpu_count(logical=False)}")
    print(f"論理コア数: {psutil.cpu_count(logical=True)}")
    print(f"合計メモリ: {psutil.virtual_memory().total / 1024 / 1024 / 1024:.2f} GB")

    all_results = []
    small_test_sizes = [128, 256, 512]

    # 各種計算のテスト
    results = compare_performance("行列乗算 (FP32)", matrix_multiplication, small_test_sizes)
    all_results.extend(results)

    if torch.cuda.is_available():
        results = compare_performance("行列乗算 (FP16)", matrix_multiplication_fp16, small_test_sizes)
        all_results.extend(results)

    results = compare_performance("行列加算", matrix_addition, small_test_sizes)
    all_results.extend(results)

    results = compare_performance("バッチ行列乗算", batch_matrix_multiplication, small_test_sizes)
    all_results.extend(results)

    results = compare_performance("ニューラルネットワーク順伝播", neural_network_forward, [128, 256, 512])
    all_results.extend(results)

    results = compare_performance("畳み込み操作", convolution_operation, [64, 128, 256])
    all_results.extend(results)

    # 結果の表示
    print("\n==== 性能比較結果サマリー ====")
    import pandas as pd
    df = pd.DataFrame(all_results)
    pd.set_option("display.max_rows", None)
    pd.set_option("display.width", 200)
    print(df)

    print("\n==== テスト完了 ====")
    print("問題がある場合は以下を確認してください")
    print("1. nvidia-smi が正常に動作するか")
    print("2. CUDA と PyTorch のバージョンが互換性があるか")
    print("3. Docker に適切な GPU フラグが設定されているか")

    print("\n現在のシステムリソース使用状況")
    print(f"CPU 使用率: {psutil.cpu_percent(interval=1)}%")
    print(f"メモリ使用率: {psutil.virtual_memory().percent}%")

    if torch.cuda.is_available():
        for i in range(torch.cuda.device_count()):
            gpu_util = torch.cuda.utilization(i)
            gpu_mem = torch.cuda.memory_allocated(i) / torch.cuda.get_device_properties(i).total_memory * 100
            print(f"GPU {i} 使用率: {gpu_util}%")
            print(f"GPU {i} メモリ使用率: {gpu_mem:.2f}%")
EOF

重要な機能:

CUDA 環境診断スクリプトの作成

目的: Docker コンテナ内での CUDA 環境を診断する。

cat > check_cuda_env.sh << 'EOF'
#!/bin/bash
echo "==== Docker コンテナ内 CUDA/GPU 環境チェック ===="

echo -e "\n1. システム情報"
uname -a
lscpu | grep "Model name"

echo -e "\n2. NVIDIA ドライバー情報"
if command -v nvidia-smi &> /dev/null; then
    nvidia-smi
else
    echo "警告: nvidia-smi が見つかりません。"
fi

echo -e "\n3. CUDA バージョン"
if command -v nvcc &> /dev/null; then
    nvcc --version
else
    echo "警告: nvcc が見つかりません。"
fi

echo -e "\n4. cuDNN バージョン"
if [ -f /usr/include/cudnn.h ]; then
    grep CUDNN_MAJOR -A 2 /usr/include/cudnn.h
elif [ -f /usr/local/cuda/include/cudnn.h ]; then
    grep CUDNN_MAJOR -A 2 /usr/local/cuda/include/cudnn.h
else
    echo "警告: cudnn.h が見つかりません。"
fi

echo -e "\n5. Python と PyTorch 情報"
python3 -c "import torch; print(\"PyTorch バージョン:\", torch.__version__, \"\nCUDA 利用可能:\", torch.cuda.is_available(), \"\nCUDA バージョン:\", torch.version.cuda if torch.cuda.is_available() else \"N/A\")"

echo -e "\n6. 環境変数"
echo "PATH=$PATH"
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"

echo -e "\n7. GPU 情報"
python3 -c "import torch; [print(f\"GPU {i}: {torch.cuda.get_device_name(i)}, メモリ: {torch.cuda.get_device_properties(i).total_memory / 1024 / 1024 / 1024:.2f} GB\") for i in range(torch.cuda.device_count())] if torch.cuda.is_available() else print(\"GPU は利用できません\")"

echo "==== 環境チェック完了 ===="
EOF

chmod +x check_cuda_env.sh

実行スクリプトの作成

目的: Dockerfile からイメージをビルドし、GPU 対応でコンテナを実行する。

cat > run_gpu_comparison.sh << 'EOF'
#!/bin/bash
echo "===== GPU vs CPU 性能比較テスト ====="

cd "$(dirname "$0")"

echo "1. Docker が利用可能か確認しています..."
if ! command -v docker &> /dev/null; then
    echo "エラー: Docker がインストールされていません"
    exit 1
fi

echo "2. GPU サポートが有効か確認しています..."
if ! docker info | grep -i nvidia &> /dev/null; then
    echo "警告: Docker の NVIDIA サポートが検出されませんでした"
fi

echo "3. NVIDIA ドライバーを確認しています..."
if ! nvidia-smi &> /dev/null; then
    echo "エラー: NVIDIA GPU が見つかりません"
    exit 1
fi

echo "4. Docker イメージをビルドしています..."
docker build -t gpu-cpu-comparison .

echo "5. GPU サポート付きでコンテナを実行しています..."
docker run --rm --gpus all \
    -e NVIDIA_VISIBLE_DEVICES=all \
    -e NVIDIA_DRIVER_CAPABILITIES=compute,utility \
    gpu-cpu-comparison bash -c "/app/check_cuda_env.sh && python3 /app/gpu_cpu_comparison.py"
EOF

docker-compose.yml の作成

目的: 複数のサービスを統一的に管理する。

メリット: docker-compose run コマンドで各サービスを個別に実行できる。

cat > docker-compose.yml << 'EOF'
version: '3.8'

services:
  gpu-benchmark:
    build:
      context: .
      dockerfile: Dockerfile
    image: gpu-cpu-comparison
    container_name: gpu-benchmark
    volumes:
      - ./:/app
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    command: python3 /app/gpu_cpu_comparison.py

  cuda-check:
    build:
      context: .
      dockerfile: Dockerfile
    image: gpu-cpu-comparison
    container_name: cuda-check
    volumes:
      - ./:/app
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    command: /app/check_cuda_env.sh

  jupyter:
    build:
      context: .
      dockerfile: Dockerfile
    image: gpu-cpu-comparison
    container_name: jupyter-gpu
    ports:
      - "8888:8888"
    volumes:
      - ./:/app
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    command: >
      bash -c "pip3 install jupyter &&
      jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root --NotebookApp.token='gpu-test'"
EOF

使用方法説明スクリプトの作成

cat > run_with_compose.sh << 'EOF'
#!/bin/bash
echo "===== Docker Compose を使用した GPU テスト環境 ====="

cd "$(dirname "$0")"

if ! command -v docker-compose &> /dev/null; then
    echo "エラー: docker-compose がインストールされていません"
    exit 1
fi

echo "以下のコマンドでサービスを実行できます"
echo "1. ベンチマークテスト: docker-compose run gpu-benchmark"
echo "2. CUDA 環境チェック: docker-compose run cuda-check"
echo "3. Jupyter Notebook: docker-compose up jupyter"
echo "   (Jupyter URL は http://localhost:8888 でトークンは 'gpu-test')"
echo ""
echo "すべてのサービスをビルド: docker-compose build"
echo "すべてのサービスを停止: docker-compose down"
EOF

chmod +x run_with_compose.sh

トラブルシューティング

cat > troubleshooting.md << 'EOF'
# WSL2 と Docker と GPU 環境のトラブルシューティング

## GPU 使用時のメモリリーク問題

**症状**: WSL2 上で GPU を使用した後、メモリが解放されない

**解決策 1**: WSL を再起動する
wsl --shutdown
EOF
cat >> troubleshooting.md << 'EOF'

WSL2 を完全にシャットダウンし、メモリを解放する。数秒後に WSL2 は自動的に再起動される。

**解決策 2**: WSL2 のメモリ制限を設定する

%UserProfile%\.wslconfig ファイルを作成して次の内容を記述する。

```
[wsl2]
memory=8GB
swap=4GB
```

設定変更後は `wsl --shutdown` で再起動が必要である。

## CUDA 関連エラー

**症状**: CUDA error: no CUDA-capable device is detected

**解決策**:

1. NVIDIA ドライバーの再インストール
2. Docker Desktop で GPU サポートが有効化されているか確認

ホスト側の NVIDIA ドライバーが WSL2 に対応しているか確認する。Docker Engine の設定で nvidia runtime が登録されているか確認する。
EOF

Miniconda3 を使用した Ubuntu 開発環境の構築

目的: Ubuntu 24.04 のコンテナで、Miniconda3 を用いて Python 3.12 環境を構築する。科学技術計算ライブラリを導入し、Jupyter Notebook を設定する。

注意: 次の手順 2、3 のコマンドは、コンテナ内で実行すること。

Ubuntu 24.04 コンテナの作成

目的: Jupyter Notebook 用のポートマッピングと自動再起動機能を備えたコンテナを起動する。

メリット: ホストのブラウザから http://localhost:8888 で Jupyter Notebook にアクセスできる。

docker run --name myubuntu --restart unless-stopped -p 8888:8888 -it ubuntu:24.04 /bin/bash

オプション説明:

Miniconda3 のインストールと環境設定

目的: 基本ツールをインストールし、Miniconda3 をセットアップし、Python 3.12 の開発環境を構築する。

メリット: システム Python と独立した環境により、パッケージのバージョン競合を回避できる。

コンテナ内で次のコマンドを実行する。

apt update && apt upgrade -y
apt install -y wget curl git cmake build-essential
rm -rf /var/lib/apt/lists/*

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/conda
rm Miniconda3-latest-Linux-x86_64.sh

/opt/conda/bin/conda init
. /opt/conda/etc/profile.d/conda.sh
echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc

source ~/.bashrc

conda create -n dev python=3.12 -y

conda activate dev

conda install -y numpy pandas matplotlib scikit-learn jupyter pylint pytest black
echo "conda activate dev" >> ~/.bashrc

jupyter notebook --generate-config
echo "c.NotebookApp.ip = '*'" >> ~/.jupyter/jupyter_notebook_config.py
echo "c.NotebookApp.port = 8888" >> ~/.jupyter/jupyter_notebook_config.py
echo "c.NotebookApp.allow_root = True" >> ~/.jupyter/jupyter_notebook_config.py

インストールされるパッケージ:

環境の確認

Python バージョンの確認

python --version

conda 環境の確認

conda info

conda 環境一覧の確認

conda env list

インストールされたパッケージの確認

conda list

このコマンドにより、必要なパッケージが正しくインストールされているか確認できる。