- Published on
LG U+ GPU Software Engineer完全合格ガイド:CUDA・vGPU・InfiniBandからK8s GPUスケジューリングまで
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 1. GPU Software Engineerという希少(きしょう)なキャリア
- 2. JDライン・バイ・ライン解剖(かいぼう)
- 3. GPUアーキテクチャ深掘り
- 4. GPU仮想化(かそうか)技術
- 5. 高速ネットワーク:InfiniBandとRDMA
- 6. Kubernetes GPU管理(かんり)
- 7. AIワークロード最適化(さいてきか)
- 8. Linuxシステムトラブルシューティング
- 9. 面接(めんせつ)予想質問30選
- 10. 10ヶ月学習ロードマップ
- 11. ポートフォリオプロジェクト3選
- 12. クイズ
- 13. 参考資料(さんこうしりょう)
1. GPU Software Engineerという希少(きしょう)なキャリア
「GPUを使う人」vs「GPUを働かせる人」
2024年以降、AI業界(ぎょうかい)を貫くキーワードは「GPU」です。あらゆる企業がGPUの確保に奔走していますが、確保したGPUを適切に運用できるエンジニアはごく少数です。
ここで決定的な区別が必要です:
| 区分 | GPUを使う人 | GPUを働かせる人 |
|---|---|---|
| 役割 | ML Engineer, Researcher | GPU Software Engineer |
| 関心事 | モデル精度、学習アルゴリズム | GPU稼働率、メモリ帯域幅、スケジューリング |
| 使用ツール | PyTorch, TensorFlow | nvidia-smi, Nsight, DCGM, NCCL |
| 主な疑問 | 「このモデルの性能が出ないのはなぜ?」 | 「このGPUが70%しか使われていないのはなぜ?」 |
| 抽象化レベル | Python API | CUDAカーネル、ドライバ、ハイパーバイザ |
| 対応領域 | モデルアーキテクチャ変更 | XIDエラー分析、PCIeボトルネック解消、MIG設定 |
ML Engineerが PyTorchで model.to('cuda') を呼び出すと、GPU Software Engineerはその呼び出しがどのパスを通り、どのドライバコールを経て、どのメモリ領域に割り当てられるかを理解し最適化します。
この役割の市場価値(しじょうかち)
GPU Software Engineerの需給(じゅきゅう)不均衡は深刻です:
- 需要側: 2025年基準で世界中のデータセンターに設置されたNVIDIA GPUは約500万枚以上。毎年数百万枚が追加配備されており、これを運用するシステムエンジニアが必要です。
- 供給側: GPUシステムソフトウェアを深く理解するエンジニアは、従来NVIDIA社内、HPC研究所、大手クラウド事業者にのみ存在していました。韓国市場ではこの人材プールが極めて限定的です。
- 年収プレミアム: 米国基準でGPU/CUDA Engineerのbase salaryは250K〜400K USDが一般的であり、韓国でもこの分野の専門家に破格の待遇を提供するケースが増加しています。
LG U+ GPU技術TFのミッション
LG U+がGPU技術TFを新設した背景を理解する必要があります:
- 通信事業者のAIインフラ事業: LG U+は自社AIサービスだけでなく、法人顧客にGPUクラウドを提供する事業を推進しています。
- GPUマルチテナンシー: 1枚のGPUを複数の顧客が分けて使うにはvGPU/MIG技術が必須です。
- ネットワークの強み活用: 通信事業者としてInfiniBand/RoCE高速ネットワーク設計の能力があります。
- エンドツーエンド最適化: ハードウェア選定から仮想化、コンテナ、AIワークロードオンボーディングまで全区間を担当するチームです。
関連職種(しょくしゅ)の比較
| 職種 | コア能力 | GPU深度 | インフラ深度 |
|---|---|---|---|
| ML Engineer | モデル開発、学習パイプライン | 低い(API水準) | 低い |
| MLOps Engineer | CI/CD、モデルサービング、パイプライン自動化 | 中程度 | 中程度 |
| GPU SW Engineer | GPUアーキテクチャ、仮想化、ドライバ | 非常に高い | 高い |
| Infra SRE | サーバ/ネットワーク可用性、モニタリング | 中程度 | 非常に高い |
| HPC Engineer | 並列コンピューティング、MPI、スケジューラ | 高い | 高い |
GPU Software Engineerはこれら全職種の**交差点(こうさてん)**に位置し、特にハードウェアに最も近いソフトウェアレイヤーを担当します。
2. JDライン・バイ・ライン解剖(かいぼう)
LG U+ GPU Software Engineer JDの各項目が実際に意味することを分析します。
担当業務
「GPUリソース管理および性能最適化」
これは単にnvidia-smiを監視することではありません。具体的には:
- GPU稼働率(SM Occupancy)が期待以下の場合、原因を特定し解決
- HBMメモリ帯域幅稼働率の分析とカーネルレベルの最適化
- 電力制限(Power Capping)と性能のトレードオフ管理
- ECCエラー発生時のRMA判断と対応
- クラスタ単位のGPU割り当てポリシー設計
「GPU仮想化技術の開発および最適化」
これがこのポジションの核心的な差別化ポイントです:
- vGPUプロファイル設計:どの顧客にどのサイズの仮想GPUを割り当てるか
- MIGパーティショニング戦略:A100/H100のMIGプロファイルをワークロードに合わせて構成
- PCI Passthrough vs vGPU vs MIG間の技術選択基準の策定
- KubeVirt環境でVMにGPUを割り当てるパイプライン構築
「AI/MLワークロードのGPUオンボーディングおよび性能最適化」
顧客が持ち込むAIモデルをGPUインフラに効率的にデプロイする作業:
- モデルプロファイリング:GPUメモリ要求量、演算要求量の分析
- 適切なGPUタイプ/サイズのマッチング(A100-40GB vs A100-80GB vs H100)
- 分散学習設定:NCCL通信最適化、InfiniBand活用
- 推論サービング:Triton Inference Server設定、バッチサイズ最適化
応募資格(おうぼしかく)の分析
「コンピュータサイエンス学士以上(システム/ネットワーク/OS専攻修士優遇)」
修士優遇の理由は明確です。この分野の知識はほとんどが大学院レベルの科目で扱われます:
- オペレーティングシステム:メモリ管理、スケジューリング、デバイスドライバ
- コンピュータアーキテクチャ:キャッシュ階層、メモリモデル、並列処理
- ネットワーク:RDMA、高性能プロトコル
「GPUまたはシステムソフトウェアの実務経験」
核心キーワードは「システムソフトウェア」です。これは:
- カーネルモジュールの開発/デバッグ経験
- デバイスドライバとの相互作用
- 低レベル性能プロファイリング(perf, ftrace, eBPF)
- C/C++レベルのシステムプログラミング
必須技術の分析
次のセクションで各必須技術を深掘りします。
3. GPUアーキテクチャ深掘り
3-1. GPU演算構造(えんざんこうぞう)
SM(Streaming Multiprocessor)アーキテクチャ
GPUの中核演算ユニットはSM(Streaming Multiprocessor)です。現代のNVIDIA GPUのSM構造を理解することが、すべてのGPU最適化の出発点です。
SM内部の構成要素:
SM (Streaming Multiprocessor)
├── CUDA Cores (INT32 + FP32)
│ └── H100: SM当たり128個のFP32コア
├── Tensor Cores
│ └── H100: SM当たり第4世代Tensor Core (FP8対応)
├── RT Cores (Ray Tracing, データセンターでは未使用)
├── Warp Scheduler (4個)
│ └── 各スケジューラが独立してwarpをディスパッチ
├── Register File (256KB per SM in H100)
├── Shared Memory / L1 Cache (統合、最大228KB)
├── Load/Store Units
├── Special Function Units (SFU)
│ └── sin, cos, expなど超越関数の計算
└── Texture Units
WarpとSIMTモデル:
GPU実行の基本単位は**Warp(32個のスレッド)**です。同一Warp内のすべてのスレッドは同じ命令を同時に実行します。これがSIMT(Single Instruction, Multiple Threads)モデルです。
Grid (全体の作業)
├── Block 0
│ ├── Warp 0 (Thread 0~31) → 同じ命令を同時実行
│ ├── Warp 1 (Thread 32~63) → 同じ命令を同時実行
│ └── Warp N ...
├── Block 1
│ ├── Warp 0
│ └── ...
└── Block M
Warp Divergenceの問題:Warp内のスレッドが異なる分岐(if/else)を取ると、両方の分岐を逐次実行するため性能が低下します。これを「Warp Divergence」と呼び、GPUプログラミングで必ず避けるべきパターンです。
// 悪い例: Warp Divergence発生
__global__ void kernel(float* data, int n) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx % 2 == 0) {
data[idx] = expensive_operation_A(data[idx]);
} else {
data[idx] = expensive_operation_B(data[idx]);
}
// Warp内の偶数/奇数スレッドが異なる分岐 → 逐次実行
}
// 良い例: 同一Warp内のスレッドが同じ分岐を取るよう設計
__global__ void kernel_optimized(float* data, int n) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
int warp_id = idx / 32;
if (warp_id % 2 == 0) {
data[idx] = expensive_operation_A(data[idx]);
} else {
data[idx] = expensive_operation_B(data[idx]);
}
// 同一Warpの全スレッドが同じ分岐
}
アーキテクチャ世代別比較
| 特性 | Ampere (A100) | Hopper (H100) | Blackwell (B200) |
|---|---|---|---|
| SM数 | 108 | 132 | 192 |
| CUDA Cores | 6,912 | 16,896 | 21,760+ |
| Tensor Cores | 432 (第3世代) | 528 (第4世代) | 768 (第5世代) |
| メモリ | HBM2e 80GB | HBM3 80GB | HBM3e 192GB |
| メモリ帯域幅 | 2.0 TB/s | 3.35 TB/s | 8.0 TB/s |
| NVLink | 3.0 (600GB/s) | 4.0 (900GB/s) | 5.0 (1.8TB/s) |
| Transformer Engine | なし | FP8対応 | FP4対応 |
| MIG対応 | 最大7インスタンス | 最大7インスタンス | 最大7インスタンス |
| TDP | 400W | 700W | 1000W |
| FP16 Tensor性能 | 312 TFLOPS | 989 TFLOPS | 2,250+ TFLOPS |
Transformer Engine:H100から導入されたTransformer EngineはFP8精度をハードウェアレベルでサポートします。学習中に各レイヤーのテンソルを動的にFP8/FP16間で切り替え、メモリ使用量を半減しながら精度損失を最小化します。
NVLinkとNVSwitch:GPU間の高速直接通信パスです。
NVLinkトポロジ (DGX H100基準):
GPU 0 <── NVLink 4.0 (900GB/s) ──> GPU 1
| |
NVSwitch (完全接続) NVSwitch
| |
GPU 2 <── NVLink 4.0 (900GB/s) ──> GPU 3
| |
... 8-GPU 完全接続 ...
GPU 6 <── NVLink 4.0 (900GB/s) ──> GPU 7
総帯域幅: 8 GPU x 900GB/s = 7.2TB/s (双方向)
3-2. GPUメモリ階層(かいそう)(最重要!)
GPUメモリ階層を理解することはGPU性能最適化の**80%**を占めます。すべてのGPU性能問題は最終的にメモリ問題に帰結します。
メモリ階層 (速い → 遅い):
1. Register (最速)
├── 容量: スレッド当たり最大255個 (32ビット)
├── 遅延: ~1 cycle
├── 帯域幅: 無限 (ALUに直接接続)
└── 特徴: コンパイラが自動割り当て、超過時local memoryにspill
2. Shared Memory
├── 容量: SM当たり48KB ~ 228KB (設定可能)
├── 遅延: ~5 cycles (register比 ~5x遅い)
├── 帯域幅: ~19TB/s (H100基準)
├── 特徴: 同一Block内のスレッド間で共有
└── 注意: Bank Conflict発生の可能性
3. L1 Cache
├── Shared Memoryと統合 (設定で比率調整)
├── H100: Shared Memory + L1 = 228KB per SM
└── 自動キャッシュ、プログラマが直接制御しない
4. L2 Cache
├── 容量: H100 = 50MB (全SM共有)
├── 遅延: ~200 cycles
└── A100: 40MB, Blackwell: 最大128MB
5. Global Memory (HBM)
├── 容量: 40GB ~ 192GB
├── 遅延: ~600 cycles (register比 ~600x遅い)
├── 帯域幅: 2.0 ~ 8.0 TB/s (世代別)
└── すべてのスレッドからアクセス可能
メモリ帯域幅稼働率の計算:
GPU性能がメモリボトルネック(Memory-Bound)か演算ボトルネック(Compute-Bound)かを判別することが核心です。
Arithmetic Intensity (算術強度) = FLOPs / Bytes Accessed
H100基準:
- Peak Compute: 989 TFLOPS (FP16 Tensor)
- Peak Memory BW: 3.35 TB/s
均衡点 (Roofline分析):
989 TFLOPS / 3.35 TB/s = 295 FLOPs/Byte
→ 算術強度が295より低ければMemory-Bound
→ 算術強度が295より高ければCompute-Bound
実際の例:
- ベクトル加算: 1 FLOP / 12 Bytes = 0.08 → 極度にMemory-Bound
- 行列乗算 (NxN): 2N FLOPs / 8 Bytes ≈ O(N) → Nが大きければCompute-Bound
- Transformer Attention: 通常Memory-Bound (特に推論時)
Memory Coalescing(メモリ合併アクセス):
Warpの32個のスレッドが連続メモリにアクセスすると、ハードウェアがこれを1つの大きなトランザクションに統合します。非連続アクセスは複数のトランザクションに分離され、帯域幅の浪費が発生します。
// 良い例: Coalesced Access (連続アクセス)
// Thread 0 → data[0], Thread 1 → data[1], ..., Thread 31 → data[31]
__global__ void coalesced(float* data) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
float val = data[idx]; // 128-byteトランザクション1つ
}
// 悪い例: Strided Access (非連続アクセス)
// Thread 0 → data[0], Thread 1 → data[32], ..., Thread 31 → data[31*32]
__global__ void strided(float* data, int stride) {
int idx = (blockIdx.x * blockDim.x + threadIdx.x) * stride;
float val = data[idx]; // 32個の個別トランザクション!
}
Bank Conflict:
Shared Memoryは32個のバンク(Bank)に分かれています。同一Warp内で2つ以上のスレッドが同じバンクにアクセスすると逐次処理され、性能が低下します。
Shared Memoryバンク構造 (4バイト単位):
Bank 0: addr 0, 128, 256, ...
Bank 1: addr 4, 132, 260, ...
Bank 2: addr 8, 136, 264, ...
...
Bank 31: addr 124, 252, 380, ...
Bank Conflictの例:
Thread 0 → Bank 0 (addr 0)
Thread 1 → Bank 0 (addr 128) ← 同じバンク! 衝突
→ 2-way bank conflict: 2倍遅くなる
回避方法: パディング追加
__shared__ float tile[32][33]; // 33にパディング (32の代わりに)
// 列アクセス時にBank Conflictを回避
3-3. CUDAプログラミング基礎(きそ)
Grid, Block, Thread階層
CUDA実行モデル:
Grid (1個)
├── Block (0,0) ── Block (1,0) ── Block (2,0)
├── Block (0,1) ── Block (1,1) ── Block (2,1)
└── Block (0,2) ── Block (1,2) ── Block (2,2)
各Block:
├── Thread (0,0) ... Thread (15,0)
├── Thread (0,1) ... Thread (15,1)
└── Thread (0,15) ... Thread (15,15)
制約:
- Block当たり最大1024スレッド
- Block次元: 最大 (1024, 1024, 64)
- Grid次元: 最大 (2^31-1, 65535, 65535)
CUDAコード例:ベクトル加算
#include <stdio.h>
#include <cuda_runtime.h>
// GPUカーネル関数
__global__ void vectorAdd(const float* A, const float* B, float* C, int n) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < n) {
C[idx] = A[idx] + B[idx];
}
}
int main() {
int n = 1 << 20; // 1M要素
size_t size = n * sizeof(float);
// ホストメモリ割り当て
float *h_A = (float*)malloc(size);
float *h_B = (float*)malloc(size);
float *h_C = (float*)malloc(size);
// 初期化
for (int i = 0; i < n; i++) {
h_A[i] = 1.0f;
h_B[i] = 2.0f;
}
// デバイスメモリ割り当て
float *d_A, *d_B, *d_C;
cudaMalloc(&d_A, size);
cudaMalloc(&d_B, size);
cudaMalloc(&d_C, size);
// ホスト → デバイスコピー
cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);
// カーネル実行
int blockSize = 256;
int gridSize = (n + blockSize - 1) / blockSize;
vectorAdd<<<gridSize, blockSize>>>(d_A, d_B, d_C, n);
// デバイス → ホストコピー
cudaMemcpy(h_C, d_C, size, cudaMemcpyDeviceToHost);
// 検証
printf("C[0] = %f (expected 3.0)\n", h_C[0]);
// メモリ解放
cudaFree(d_A); cudaFree(d_B); cudaFree(d_C);
free(h_A); free(h_B); free(h_C);
return 0;
}
CUDAコード例:行列乗算(Shared Memory活用)
#define TILE_SIZE 32
__global__ void matMul(const float* A, const float* B, float* C, int N) {
__shared__ float tileA[TILE_SIZE][TILE_SIZE];
__shared__ float tileB[TILE_SIZE][TILE_SIZE];
int row = blockIdx.y * TILE_SIZE + threadIdx.y;
int col = blockIdx.x * TILE_SIZE + threadIdx.x;
float sum = 0.0f;
for (int t = 0; t < (N + TILE_SIZE - 1) / TILE_SIZE; t++) {
// Global Memory → Shared Memoryロード
if (row < N && t * TILE_SIZE + threadIdx.x < N)
tileA[threadIdx.y][threadIdx.x] = A[row * N + t * TILE_SIZE + threadIdx.x];
else
tileA[threadIdx.y][threadIdx.x] = 0.0f;
if (col < N && t * TILE_SIZE + threadIdx.y < N)
tileB[threadIdx.y][threadIdx.x] = B[(t * TILE_SIZE + threadIdx.y) * N + col];
else
tileB[threadIdx.y][threadIdx.x] = 0.0f;
__syncthreads(); // Block内の全スレッド同期
for (int k = 0; k < TILE_SIZE; k++)
sum += tileA[threadIdx.y][k] * tileB[k][threadIdx.x];
__syncthreads();
}
if (row < N && col < N)
C[row * N + col] = sum;
}
主要CUDAライブラリ
| ライブラリ | 用途 | 核心API |
|---|---|---|
| cuBLAS | 線形代数(行列演算) | cublasSgemm, cublasGemmEx |
| cuDNN | ディープラーニングプリミティブ | cudnnConvolutionForward |
| cuFFT | Fast Fourier Transform | cufftExecC2C |
| cuSPARSE | 疎行列演算 | cusparseSpMV |
| Thrust | C++並列アルゴリズム(STL-like) | thrust::sort, thrust::reduce |
| CUTLASS | GEMMカスタマイズ | テンプレートベースGEMM |
3-4. GPUプロファイリングと性能分析(ぶんせき)
nvidia-smi 詳細活用
# 基本状態確認
nvidia-smi
# 1秒間隔モニタリング
nvidia-smi dmon -s pucvmet -d 1
# GPUプロセス詳細情報
nvidia-smi pmon -d 1
# クエリフォーマット(スクリプトで活用)
nvidia-smi --query-gpu=timestamp,gpu_bus_id,utilization.gpu,utilization.memory,memory.used,memory.total,temperature.gpu,power.draw --format=csv -l 1
# MIG状態確認
nvidia-smi mig -lgi
nvidia-smi mig -lci
# GPUトポロジ確認(NVLink接続状態)
nvidia-smi topo -m
# ECCエラー確認
nvidia-smi --query-gpu=ecc.errors.corrected.volatile.total,ecc.errors.uncorrected.volatile.total --format=csv
NVIDIA Nsight Systems(システムレベルプロファイリング)
# アプリケーション全体のプロファイリング
nsys profile --stats=true -o report python train.py
# CUDA API呼び出し + GPUカーネル + メモリ転送追跡
nsys profile --trace=cuda,nvtx,osrt -o detailed_report python train.py
# 結果可視化 (GUI)
nsys-ui report.nsys-rep
Nsight Systemsはタイムラインビューを提供し:
- CPUとGPU間の同期ポイントの把握
- カーネル実行とメモリ転送のオーバーラップ確認
- CPUボトルネック(データロード、前処理)の特定
- NCCL通信時間の測定(分散学習)
NVIDIA Nsight Compute(カーネルレベル分析)
# 特定カーネルの詳細分析
ncu --target-processes all --set full -o kernel_report python train.py
# 特定カーネルのみプロファイリング
ncu --kernel-name "volta_sgemm" --launch-count 10 -o sgemm_report ./my_app
# 主要メトリクス確認
ncu --metrics sm__throughput.avg.pct_of_peak_sustained_active,dram__throughput.avg.pct_of_peak_sustained_active ./my_app
核心メトリクス:
- SM Occupancy: SMのアクティブWarp比率(高いほど良い、通常50%以上が目標)
- Compute Throughput: 演算処理率(ピーク比 %)
- Memory Throughput: メモリ帯域幅稼働率(ピーク比 %)
- Warp Stall Reasons: Warpが待機する原因(メモリ待ち、同期など)
DCGM(Data Center GPU Manager)
大規模クラスタを監視する際、nvidia-smiだけでは不十分です。DCGMは:
# DCGM起動
sudo systemctl start nvidia-dcgm
# ヘルスチェック
dcgmi health -g 0 -c
# 診断実行 (Level 3: 最も詳細)
dcgmi diag -r 3 -g 0
# メトリクス収集 (Prometheus連携)
dcgm-exporter &
# http://localhost:9400/metrics からPrometheusが収集
GPU稼働率が低い原因の分析パターン
GPU Utilization 低い (<50%)
├── CPUボトルネック?
│ ├── データロードが遅い → num_workers増加、prefetch
│ ├── 前処理が重い → DALI(GPU前処理)使用
│ └── Python GIL → マルチプロセシング
├── メモリ転送ボトルネック?
│ ├── PCIe帯域幅飽和 → GPU Direct活用
│ └── 不要なCPU-GPUコピー → 固定メモリ(pinned memory)使用
├── 小さなカーネル + 大きなオーバーヘッド?
│ ├── カーネルラウンチオーバーヘッド → CUDA Graph使用
│ └── 過剰な同期 → 非同期実行最適化
├── バッチサイズが小さい?
│ └── GPUを十分に埋められない → バッチ増加またはGradient Accumulation
└── 通信オーバーヘッド? (分散学習)
├── AllReduce時間が長い → NCCLチューニング
└── ネットワークボトルネック → InfiniBand確認
4. GPU仮想化(かそうか)技術
4-1. 仮想化の基礎
Type 1 vs Type 2 ハイパーバイザ
Type 1 (Bare-metal): Type 2 (Hosted):
┌─────────────────┐ ┌─────────────────┐
│ VM1 VM2 │ │ VM1 VM2 │
│ ┌─────┐┌─────┐ │ │ ┌─────┐┌─────┐ │
│ │Guest││Guest│ │ │ │Guest││Guest│ │
│ │ OS ││ OS │ │ │ │ OS ││ OS │ │
│ └─────┘└─────┘ │ │ └─────┘└─────┘ │
│ Hypervisor │ │ Hypervisor │
│ (ESXi, KVM) │ │ (VirtualBox) │
│ Hardware │ │ Host OS │
└─────────────────┘ │ Hardware │
└─────────────────┘
LG U+環境ではKVMが核心です。KVMはLinuxカーネルモジュールとして動作するType 1ハイパーバイザであり、QEMUをユーザ空間エミュレータとして使用します。
IOMMU (Intel VT-d / AMD-Vi)
IOMMUはGPU仮想化の必須ハードウェア機能です:
IOMMUなし (安全でない):
VM → (仮想アドレス) → 物理メモリ (直接アクセス → 他VMのメモリ侵犯可能)
IOMMUあり (安全):
VM → (仮想アドレス) → IOMMU変換 → (物理アドレス、隔離済み)
└── DMA要求も隔離!
IOMMU有効化の確認:
# IOMMUグループ確認
find /sys/kernel/iommu_groups/ -type l
# カーネルブートパラメータ確認
cat /proc/cmdline | grep iommu
# intel_iommu=on または amd_iommu=on であること
# IOMMUグループ別デバイス確認
for g in /sys/kernel/iommu_groups/*/devices/*; do
echo "IOMMU Group $(basename $(dirname $(dirname $g))):"
lspci -nns $(basename $g)
done
4-2. PCI Passthrough
PCI Passthroughは物理GPUをVMに直接割り当てる最も基本的な方式です。
PCI Passthroughアーキテクチャ:
Host (Linux + KVM)
├── GPU 0 → VFIOドライババインディング → VM1 (直接アクセス)
├── GPU 1 → VFIOドライババインディング → VM2 (直接アクセス)
├── GPU 2 → NVIDIAドライバ → Host使用
└── GPU 3 → NVIDIAドライバ → Host使用
設定手順:
# 1. IOMMU有効化 (GRUB)
# /etc/default/grub に追加:
# GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt"
# 2. GPUのPCI ID確認
lspci -nn | grep NVIDIA
# 41:00.0 3D controller [0302]: NVIDIA Corporation A100 [10de:20b2]
# 3. VFIOドライバにバインディング
echo "10de 20b2" > /sys/bus/pci/drivers/vfio-pci/new_id
echo "0000:41:00.0" > /sys/bus/pci/devices/0000:41:00.0/driver/unbind
echo "0000:41:00.0" > /sys/bus/pci/drivers/vfio-pci/bind
# 4. QEMU/KVMでVM起動時にデバイス追加
# -device vfio-pci,host=41:00.0
長所と短所:
| 長所 | 短所 |
|---|---|
| ネイティブ性能 (オーバーヘッドほぼなし) | 1 GPU = 1 VM (共有不可) |
| シンプルな設定 | ライブマイグレーション不可 |
| すべてのCUDA機能に対応 | GPUリソースの浪費可能性 |
4-3. vGPU (NVIDIA Virtual GPU)
vGPUはタイムスライシング(Time-Slicing)で1つの物理GPUを複数のVMが共有します。
vGPUアーキテクチャ:
Physical GPU (A100-80GB)
├── vGPU Instance 1 (A100-4C, 4GB) → VM1
├── vGPU Instance 2 (A100-4C, 4GB) → VM2
├── vGPU Instance 3 (A100-8C, 8GB) → VM3
└── ... (残容量分だけ追加可能)
タイムスライシング:
t=0ms [VM1実行] → t=16ms [VM2実行] → t=32ms [VM3実行] → ...
vGPUプロファイルタイプ
| シリーズ | 用途 | 例 |
|---|---|---|
| A-series | Virtual Application | A100-1-5A (5GB, VDIアプリ) |
| B-series | Virtual PC | A100-2-10B (10GB, VDIデスクトップ) |
| C-series | Compute | A100-4-20C (20GB, AI演算) |
| Q-series | Quadro | A100-8-40Q (40GB, プロフェッショナルグラフィックス) |
LG U+ GPU技術TFでは**C-series(Compute)**が主力となるでしょう。
vGPU Scheduler
# vGPUスケジューラタイプ
Equal Share:
- すべてのvGPUに同一時間を割り当て
- 公平だが優先度設定不可
Fixed Share:
- vGPUプロファイルサイズに比例して時間割り当て
- 4GB vGPU: 8GB vGPU = 1:2 時間
Best Effort:
- アイドルvGPUの時間をアクティブvGPUに再分配
- 最も効率的だが性能予測が困難
4-4. MIG (Multi-Instance GPU)
MIGはA100/H100専用技術で、GPUを物理的に分割します。vGPUのタイムスライシングとは異なり、MIGはSMとメモリを完全に隔離します。
MIGアーキテクチャ (A100-80GB):
全体GPU: 108 SM, 80GB HBM2e
├── MIG Instance 1 (7g.80gb): 98 SM, 80GB ← ほぼ全体 (単独使用)
または
├── MIG Instance 1 (4g.40gb): 56 SM, 40GB
├── MIG Instance 2 (3g.40gb): 42 SM, 40GB
または
├── MIG Instance 1 (3g.40gb): 42 SM, 40GB
├── MIG Instance 2 (2g.20gb): 28 SM, 20GB
├── MIG Instance 3 (1g.10gb): 14 SM, 10GB
├── MIG Instance 4 (1g.10gb): 14 SM, 10GB
または (最大分割)
├── MIG Instance 1~7 (1g.10gb): 各14 SM, 各10GB (x7)
MIG設定コマンド
# MIG有効化
sudo nvidia-smi -i 0 -mig 1
# 使用可能なMIGプロファイル確認
nvidia-smi mig -lgip
# GPU Instance作成
sudo nvidia-smi mig -i 0 -cgi 9,14,14,14 # 3g.40gb + 1g.10gb x3
# Compute Instance作成
sudo nvidia-smi mig -i 0 -cci
# 現在のMIG状態確認
nvidia-smi mig -lgi
nvidia-smi mig -lci
# MIGインスタンス削除
sudo nvidia-smi mig -i 0 -dci
sudo nvidia-smi mig -i 0 -dgi
# MIG無効化
sudo nvidia-smi -i 0 -mig 0
MIG vs vGPU 比較
| 特性 | MIG | vGPU |
|---|---|---|
| 隔離レベル | 物理的 (SM + メモリ完全分離) | タイムスライシング (ソフトウェア隔離) |
| 性能予測性 | 一定 (専用リソース) | 変動可能 (他VM影響あり) |
| 最大インスタンス | 7個 (A100/H100) | GPUメモリ上限内で多数 |
| 対応GPU | A100, H100, A30 | ほとんどのデータセンターGPU |
| 柔軟性 | 固定プロファイル (変更時再構成) | 動的割り当て可能 |
| ライセンス | 追加ライセンス不要 | vGPUライセンス必要 |
| 使用ケース | 推論サービング、小規模学習 | VDI、混合ワークロード |
K8sでのMIG使用:NVIDIA MIG Manager
# MIG設定ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: mig-parted-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
mig-configs:
all-1g.10gb:
- device-filter: ["0x20B210DE"]
devices: all
mig-enabled: true
mig-devices:
"1g.10gb": 7
mixed-config:
- device-filter: ["0x20B210DE"]
devices: all
mig-enabled: true
mig-devices:
"3g.40gb": 1
"1g.10gb": 4
4-5. SR-IOV(NIC仮想化)
SR-IOVはNICを仮想化してVMに直接割り当てます。GPU Direct RDMAと組み合わせる際に重要です。
SR-IOV構造:
Physical NIC (ConnectX-7)
├── PF (Physical Function): ホストドライバ管理
├── VF 0 (Virtual Function) → VM1 (直接割り当て、ネイティブ性能)
├── VF 1 → VM2
├── VF 2 → VM3
└── ... (最大128個VF)
長所:
- 仮想ブリッジなしでVMがNICに直接アクセス
- ネイティブに近いネットワーク性能
- CPUオーバーヘッド最小化
GPU Direct RDMAとの組み合わせ:
VM内GPU <-> VF(SR-IOV NIC) <-> InfiniBand <-> リモートGPU
(PCIe直接) (SR-IOVバイパス) (RDMA)
4-6. KubeVirt
KubeVirtはKubernetes上でVMをファーストクラスリソースとして管理します。コンテナとVMを同一プラットフォームで運用する必要がある場合の核心技術です。
# KubeVirt VMにGPU PCI Passthrough
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: gpu-vm
spec:
running: true
template:
spec:
domain:
devices:
hostDevices:
- name: gpu
deviceName: nvidia.com/A100
resources:
requests:
memory: '32Gi'
cpu: '8'
volumes:
- name: rootdisk
containerDisk:
image: quay.io/containerdisks/ubuntu:22.04
KubeVirt + vGPU:
# KubeVirt VMにvGPU割り当て
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vgpu-vm
spec:
template:
spec:
domain:
devices:
gpus:
- name: vgpu
deviceName: nvidia.com/NVIDIA_A100-4C
resources:
requests:
memory: '16Gi'
使用ケース:
- レガシーVMワークロード: 既存VM基盤のAIワークロードをK8sにマイグレーション
- 混合環境: 同一K8sクラスタでコンテナ + VM同時運用
- GPU共有: vGPUを通じてVMとコンテナにGPUを柔軟に割り当て
5. 高速ネットワーク:InfiniBandとRDMA
5-1. InfiniBandアーキテクチャ
分散GPU学習の性能はネットワークによって決定されます。GPUがいくら速くても、GPU間通信が遅ければ全体性能が低下します。
InfiniBand vs Ethernet比較
| 特性 | InfiniBand NDR | RoCE v2 (100GbE) | TCP/IP (100GbE) |
|---|---|---|---|
| 帯域幅 | 400 Gbps | 100 Gbps | 100 Gbps |
| 遅延時間 | 0.5us | 1~2us | 10~50us |
| RDMAサポート | ネイティブ | RoCE v2 | なし (カーネル経由) |
| CPUオーバーヘッド | ほぼなし | 低い | 高い |
| 輻輳制御 | Credit-based | PFC/ECN | TCP輻輳制御 |
| コスト | 非常に高い | 中程度 | 低い |
| 用途 | HPC, AI学習 | AI学習 (クラウド) | 一般ワークロード |
InfiniBand世代
InfiniBand速度の進化:
SDR (2001): 10 Gbps
DDR (2005): 20 Gbps
QDR (2008): 40 Gbps
FDR (2011): 56 Gbps
EDR (2014): 100 Gbps
HDR (2018): 200 Gbps
NDR (2022): 400 Gbps
XDR (2024): 800 Gbps
GDR (2026): 1.6 Tbps (予定)
InfiniBandネットワーク構成要素
InfiniBandファブリック構造:
Leaf Switch (ToR)
├── HCA (Host Channel Adapter) ─ Server 1 [GPU 0~7]
├── HCA ─ Server 2 [GPU 0~7]
├── HCA ─ Server 3 [GPU 0~7]
└── HCA ─ Server 4 [GPU 0~7]
Spine Switch
├── Leaf Switch 1
├── Leaf Switch 2
├── Leaf Switch 3
└── Leaf Switch 4
管理要素:
- Subnet Manager (OpenSM): LID割り当て、ルーティングテーブル管理
- LID (Local ID): サブネット内アドレス (16ビット)
- GID (Global ID): グローバルアドレス (128ビット、IPv6類似)
- GUID (Globally Unique ID): ハードウェア固有識別子
5-2. RDMA(Remote Direct Memory Access)
RDMAはCPUを経由せずリモートメモリに直接アクセスする技術です。GPU分散学習の核心です。
TCP/IP転送 (従来):
App → Socket API → TCP/IP Stack (カーネル) → NIC Driver → NIC → ネットワーク
↑ CPU介入 (コピー、チェックサム、セグメンテーション)
RDMA転送:
App → RDMA Verbs → NIC (直接) → ネットワーク
↑ Zero-copy, CPUバイパス
RDMA転送タイプ
| 転送タイプ | 説明 | 使用ケース |
|---|---|---|
| InfiniBand | ネイティブRDMA | HPC, AIクラスタ |
| RoCE v2 | RDMA over UDP/IP | クラウド環境 |
| iWARP | RDMA over TCP/IP | レガシー環境 |
RDMAプログラミング基礎
// ibverbsベースのRDMA Write例 (簡略化)
#include <infiniband/verbs.h>
// 1. デバイスを開く
struct ibv_context *ctx = ibv_open_device(dev);
// 2. Protection Domain作成
struct ibv_pd *pd = ibv_alloc_pd(ctx);
// 3. メモリ登録 (NICが直接アクセスできるように)
struct ibv_mr *mr = ibv_reg_mr(pd, buf, size,
IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE);
// 4. Queue Pair作成
struct ibv_qp *qp = ibv_create_qp(pd, &qp_init_attr);
// 5. RDMA Write (リモートメモリに直接書き込み)
struct ibv_send_wr wr;
wr.opcode = IBV_WR_RDMA_WRITE;
wr.wr.rdma.remote_addr = remote_addr;
wr.wr.rdma.rkey = remote_key;
ibv_post_send(qp, &wr, &bad_wr);
5-3. GPU Direct
GPU Direct RDMA
GPU Direct RDMAを使うと、GPUメモリからリモートGPUメモリへ直接データを転送できます。
通常の経路 (GPU Directなし):
GPU0 → PCIe → Host Memory → NIC → ネットワーク → NIC → Host Memory → PCIe → GPU1
(コピー1) (コピー2) (コピー3) (コピー4)
GPU Direct RDMA:
GPU0 → PCIe → NIC → ネットワーク → NIC → PCIe → GPU1
(直接) (直接)
CPUバイパス、コピー回数2倍削減
GPU Direct Storage (GDS)
通常のストレージアクセス:
NVMe → Host Memory (bounce buffer) → GPU Memory
CPU介入、2回コピー
GPU Direct Storage:
NVMe → GPU Memory (直接)
CPUバイパス、1回コピー
使用ケース: 大規模データセットのロード (チェックポイント復旧、データ前処理)
NCCL + InfiniBandの組み合わせ
# NCCL環境変数設定 (分散学習)
export NCCL_IB_HCA=mlx5_0,mlx5_1 # InfiniBand HCA指定
export NCCL_IB_GID_INDEX=3 # RoCE v2 GIDインデックス
export NCCL_SOCKET_IFNAME=eth0 # 制御チャネルインターフェース
export NCCL_DEBUG=INFO # デバッグログ
# NCCLトポロジファイル (GPU-NICマッピング最適化)
export NCCL_TOPO_FILE=/path/to/topo.xml
# NCCL AllReduceベンチマーク
/usr/local/nccl-tests/build/all_reduce_perf -b 8 -e 1G -f 2 -g 8
5-4. ネットワーク性能チューニング
InfiniBandベンチマーク
# 帯域幅テスト
# サーバ: ib_write_bw --size=65536
# クライアント: ib_write_bw --size=65536 <server_ip>
# レイテンシテスト
# サーバ: ib_write_lat
# クライアント: ib_write_lat <server_ip>
# 結果例 (NDR 400Gbps):
# Bandwidth: ~48 GB/s (理論 50 GB/s)
# Latency: ~0.6 us
PFC (Priority Flow Control) 設定
RoCE v2環境ではPFCが必須です:
# Mellanox NIC PFC設定
mlnx_qos -i eth0 --pfc 0,0,0,1,0,0,0,0
# Priority 3のみPFC有効化 (RoCEトラフィック)
# DSCP → Priorityマッピング
mlnx_qos -i eth0 --trust dscp
ECMP (Equal-Cost Multi-Path) ルーティング
大規模InfiniBandファブリックでのECMP:
Server A ─── Leaf 1 ─┬─ Spine 1 ─┬─ Leaf 3 ─── Server C
├─ Spine 2 ─┤
├─ Spine 3 ─┤
└─ Spine 4 ─┘
→ 4つの等コスト経路をロードバランシング
→ ハッシュベース (ソース/宛先LID) 分散
→ Adaptive Routing (AR): 輻輳状態に応じた動的経路変更
6. Kubernetes GPU管理(かんり)
6-1. NVIDIA GPU Operator
GPU OperatorはK8sクラスタにGPUソフトウェアスタックを自動デプロイします。
GPU Operatorコンポーネント:
GPU Operator
├── NVIDIA Driver (DaemonSet)
│ └── カーネルモジュール自動ビルド/インストール
├── NVIDIA Container Toolkit
│ └── コンテナランタイムにGPUサポート追加
├── NVIDIA Device Plugin
│ └── K8sにGPUリソース登録
├── DCGM Exporter
│ └── GPUメトリクス → Prometheus
├── MIG Manager
│ └── MIGプロファイル自動適用
├── GPU Feature Discovery (GFD)
│ └── ノードにGPUラベル自動追加
└── NVIDIA Validator
└── インストール状態検証
インストール:
# HelmでGPU Operatorインストール
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm install gpu-operator nvidia/gpu-operator \
--namespace gpu-operator \
--create-namespace \
--set driver.enabled=true \
--set mig.strategy=mixed \
--set dcgmExporter.enabled=true
6-2. GPU Device Plugin
# PodにGPU割り当て
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
containers:
- name: cuda-container
image: nvcr.io/nvidia/cuda:12.3.0-runtime-ubuntu22.04
resources:
limits:
nvidia.com/gpu: 2 # GPU 2枚要求
command: ['nvidia-smi']
Time-Slicing設定(GPU共有)
MIGを対応しないGPUで複数PodがGPUを共有できるようにします:
# GPU Time-Slicing ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: time-slicing-config
namespace: gpu-operator
data:
any: |-
version: v1
flags:
migStrategy: none
sharing:
timeSlicing:
renameByDefault: false
failRequestsGreaterThanOne: false
resources:
- name: nvidia.com/gpu
replicas: 4 # 1 GPUを4つに分割 (タイムスライシング)
6-3. GPUスケジューリング
基本スケジューリング
K8sの基本GPUスケジューリングはシンプルです:Podが要求したGPU数だけ利用可能なノードに配置します。しかし、大規模GPUクラスタではより精緻なスケジューリングが必要です。
Topology-Aware Scheduling
DGX H100 GPUトポロジ:
GPU0 ─ NVLink ─ GPU1 (同一NVSwitchドメイン)
GPU2 ─ NVLink ─ GPU3 (同一NVSwitchドメイン)
GPU4 ─ NVLink ─ GPU5 (同一NVSwitchドメイン)
GPU6 ─ NVLink ─ GPU7 (同一NVSwitchドメイン)
GPU0 ─ PCIe ─ GPU4 (異なるドメイン、PCIe接続)
→ 4-GPU学習時: GPU0,1,2,3 (NVLink接続) >> GPU0,2,4,6 (PCIe接続)
# Topology-aware schedulingのためのNodeSelector
apiVersion: v1
kind: Pod
metadata:
name: distributed-training
spec:
nodeSelector:
nvidia.com/gpu.product: 'NVIDIA-H100-80GB-HBM3'
nvidia.com/gpu.count: '8'
containers:
- name: trainer
resources:
limits:
nvidia.com/gpu: 4
Gang Scheduling
分散学習ではすべてのGPUが同時に割り当てられる必要があります。一部のみ割り当てられると、残りを待ちながらリソースが浪費されます。
# Volcanoを使用したGang Scheduling
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: distributed-training
spec:
minAvailable: 4 # 最少4つのPodを同時スケジューリング
schedulerName: volcano
tasks:
- replicas: 4
name: worker
template:
spec:
containers:
- name: trainer
image: training-image:latest
resources:
limits:
nvidia.com/gpu: 8 # ノード当たり8 GPU
Bin-packing vs Spread戦略
Bin-packing (リソース密集):
Node1: [GPU0 使用, GPU1 使用, GPU2 使用, GPU3 空]
Node2: [GPU0 空, GPU1 空, GPU2 空, GPU3 空]
→ 長所: アイドルノードの電源節約、リソース効率性
→ 短所: ホットスポット発生の可能性
Spread (分散):
Node1: [GPU0 使用, GPU1 空, GPU2 使用, GPU3 空]
Node2: [GPU0 使用, GPU1 空, GPU2 使用, GPU3 空]
→ 長所: 負荷分散、障害隔離
→ 短所: リソースの断片化
GPU Feature Discovery (GFD)
# GFDが追加するノードラベルの例
nvidia.com/gpu.product=NVIDIA-A100-SXM4-80GB
nvidia.com/gpu.count=8
nvidia.com/gpu.memory=81920
nvidia.com/cuda.driver.major=535
nvidia.com/mig.strategy=mixed
nvidia.com/gpu.family=ampere
nvidia.com/mig-1g.10gb.count=4
nvidia.com/mig-3g.40gb.count=1
6-4. K8s上のGPUモニタリング
DCGM Exporter + Prometheus + Grafana
# DCGM Exporter DaemonSet (GPU Operatorに含まれる)
# Prometheus ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: dcgm-exporter
spec:
selector:
matchLabels:
app: nvidia-dcgm-exporter
endpoints:
- port: metrics
interval: 15s
核心Prometheusメトリクス:
# GPU稼働率
DCGM_FI_DEV_GPU_UTIL # SM稼働率 (%)
DCGM_FI_DEV_MEM_COPY_UTIL # メモリ帯域幅稼働率 (%)
# メモリ
DCGM_FI_DEV_FB_USED # 使用中のフレームバッファ (MB)
DCGM_FI_DEV_FB_FREE # 空きフレームバッファ (MB)
# 温度/電力
DCGM_FI_DEV_GPU_TEMP # GPU温度 (C)
DCGM_FI_DEV_POWER_USAGE # 電力使用量 (W)
# エラー
DCGM_FI_DEV_XID_ERRORS # XIDエラーコード
DCGM_FI_DEV_ECC_SBE_VOL_TOTAL # Single-bit ECCエラー
DCGM_FI_DEV_ECC_DBE_VOL_TOTAL # Double-bit ECCエラー
# PCIe
DCGM_FI_DEV_PCIE_TX_THROUGHPUT # PCIe送信スループット
DCGM_FI_DEV_PCIE_RX_THROUGHPUT # PCIe受信スループット
アラート設定例:
# Prometheus Alert Rules
groups:
- name: gpu-alerts
rules:
- alert: GPUMemoryAlmostFull
expr: DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE) > 0.95
for: 5m
labels:
severity: warning
annotations:
summary: 'GPU memory usage above 95%'
- alert: GPUThermalThrottling
expr: DCGM_FI_DEV_GPU_TEMP > 85
for: 2m
labels:
severity: critical
annotations:
summary: 'GPU temperature exceeds 85C'
- alert: GPUXIDError
expr: increase(DCGM_FI_DEV_XID_ERRORS[5m]) > 0
labels:
severity: critical
annotations:
summary: 'GPU XID error detected'
7. AIワークロード最適化(さいてきか)
7-1. 学習最適化
Mixed Precision Training
# PyTorch Automatic Mixed Precision (AMP)
import torch
from torch.cuda.amp import autocast, GradScaler
model = MyModel().cuda()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
scaler = GradScaler()
for data, target in dataloader:
optimizer.zero_grad()
# FP16でForward Pass
with autocast():
output = model(data.cuda())
loss = criterion(output, target.cuda())
# Loss Scaling + Backward Pass
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
精度別比較:
| 精度 | ビット | メモリ節約 | Tensor Core対応 | 用途 |
|---|---|---|---|---|
| FP32 | 32 | 基準 | O (低スループット) | 基本学習 |
| TF32 | 19 | - | O (A100+) | 自動適用 |
| FP16 | 16 | 2x | O | Mixed Precision |
| BF16 | 16 | 2x | O (A100+) | LLM学習 (より広い範囲) |
| FP8 (E4M3) | 8 | 4x | O (H100+) | Transformer Engine |
| INT8 | 8 | 4x | O | 推論量子化 |
DeepSpeed ZeRO
# DeepSpeed ZeRO Stage 3設定
# ds_config.json
{
"zero_optimization": {
"stage": 3,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"offload_param": {
"device": "cpu",
"pin_memory": true
},
"overlap_comm": true,
"contiguous_gradients": true,
"sub_group_size": 1e9,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_param_persistence_threshold": "auto",
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9
},
"bf16": {
"enabled": true
},
"train_batch_size": "auto",
"train_micro_batch_size_per_gpu": "auto"
}
ZeROメモリ分割:
ZeRO Stage 0 (基本):
GPU0: [Model] + [Gradient] + [Optimizer State]
GPU1: [Model] + [Gradient] + [Optimizer State]
→ すべてのGPUに全体複製
ZeRO Stage 1 (Optimizer分割):
GPU0: [Model] + [Gradient] + [Optimizer 1/2]
GPU1: [Model] + [Gradient] + [Optimizer 2/2]
→ メモリ ~1.5x節約
ZeRO Stage 2 (+ Gradient分割):
GPU0: [Model] + [Gradient 1/2] + [Optimizer 1/2]
GPU1: [Model] + [Gradient 2/2] + [Optimizer 2/2]
→ メモリ ~2x節約
ZeRO Stage 3 (+ Model分割):
GPU0: [Model 1/2] + [Gradient 1/2] + [Optimizer 1/2]
GPU1: [Model 2/2] + [Gradient 2/2] + [Optimizer 2/2]
→ メモリ ~N倍節約 (N = GPU数)
並列化戦略の比較
Data Parallelism:
入力データをN等分してN個のGPUで同一モデルを学習
→ AllReduceでグラディエントを同期
→ 通信量: O(model_size)
Tensor Parallelism:
1つのレイヤー(行列)をN等分してN個のGPUに分配
→ Forward/Backward各レイヤーごとに通信が必要
→ GPU間高速通信(NVLink)必須
Pipeline Parallelism:
モデルのレイヤーをN等分してN個のGPUに順次配置
→ マイクロバッチをパイプラインで処理
→ バブル(アイドル時間)の最小化が核心
3D Parallelism (LLM学習):
Data Parallel x Tensor Parallel x Pipeline Parallel
例: 256 GPU = 32 DP x 4 TP x 2 PP
7-2. 推論(すいろん)最適化
TensorRT最適化
# TensorRTによるモデル最適化 (Python API)
import tensorrt as trt
logger = trt.Logger(trt.Logger.WARNING)
builder = trt.Builder(logger)
network = builder.create_network(
1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)
)
parser = trt.OnnxParser(network, logger)
# ONNXモデルパース
with open("model.onnx", "rb") as f:
parser.parse(f.read())
# ビルド設定
config = builder.create_builder_config()
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 30) # 1GB
config.set_flag(trt.BuilderFlag.FP16) # FP16量子化有効化
# エンジンビルド
engine = builder.build_serialized_network(network, config)
Triton Inference Server
Tritonアーキテクチャ:
Client → HTTP/gRPC → Triton Server
├── Model Repository
│ ├── model_a/ (TensorRT)
│ ├── model_b/ (ONNX Runtime)
│ └── model_c/ (Python Backend)
├── Scheduler
│ ├── Dynamic Batching
│ └── Sequence Batching
├── Model Ensemble
│ └── 前処理 → モデル → 後処理パイプライン
└── Metrics (Prometheus)
# Tritonモデル設定 (config.pbtxt)
name: "my_model"
platform: "tensorrt_plan"
max_batch_size: 64
input [
{
name: "input"
data_type: TYPE_FP16
dims: [ 3, 224, 224 ]
}
]
output [
{
name: "output"
data_type: TYPE_FP16
dims: [ 1000 ]
}
]
dynamic_batching {
preferred_batch_size: [ 16, 32, 64 ]
max_queue_delay_microseconds: 100
}
instance_group [
{
count: 2
kind: KIND_GPU
gpus: [ 0 ]
}
]
vLLM: LLM推論最適化
from vllm import LLM, SamplingParams
# vLLMサーバ起動
llm = LLM(
model="meta-llama/Llama-3-70B",
tensor_parallel_size=4, # 4 GPU Tensor Parallel
gpu_memory_utilization=0.9, # GPUメモリ90%使用
max_model_len=8192,
dtype="bfloat16",
)
# 核心最適化技術:
# 1. PagedAttention: KV Cacheをページ単位で管理 (メモリ効率)
# 2. Continuous Batching: リクエストを動的にバッチに追加/削除
# 3. Prefix Caching: 共通プレフィックスのKV Cache再利用
7-3. 性能ボトルネック分析パターン
[性能問題診断フローチャート]
1. nvidia-smi確認
├── GPU Util < 30%
│ ├── CPU/IOボトルネックの可能性が高い
│ │ ├── top/htop確認 → CPU 100%? → データロード最適化
│ │ └── iostat確認 → ディスクI/O? → NVMe/GDS使用
│ └── カーネルが小さすぎる → CUDA Graph、バッチ増加
├── GPU Util > 90%, 性能低い
│ ├── Memory-Boundの可能性
│ │ ├── Nsight Compute → Memory Throughput確認
│ │ └── Memory Coalescingパターン点検
│ └── Warp Divergenceの可能性
│ └── Nsight Compute → Warp Stall Reasons
└── GPU Util 不規則 (上下変動)
├── 同期ボトルネック → 非同期実行最適化
└── 通信ボトルネック (分散) → NCCLプロファイリング
2. 分散学習ボトルネック
├── NCCL AllReduce時間確認
│ ├── Nsight SystemsでNCCL領域確認
│ └── 通信/演算比率分析
├── InfiniBand帯域幅確認
│ └── ib_write_bwベンチマーク
└── GPUトポロジ確認
└── nvidia-smi topo -m
8. Linuxシステムトラブルシューティング
8-1. GPU関連Linuxコマンド
# GPUデバイス情報
lspci -vv -s $(lspci | grep NVIDIA | head -1 | awk '{print $1}')
# GPUドライババージョン
cat /proc/driver/nvidia/version
# CUDAバージョン
nvcc --version
# GPUメモリ使用量詳細
nvidia-smi --query-gpu=memory.used,memory.free,memory.total --format=csv
# GPUプロセス別メモリ
nvidia-smi --query-compute-apps=pid,process_name,used_gpu_memory --format=csv
# PCIe帯域幅確認
nvidia-smi --query-gpu=pcie.link.gen.current,pcie.link.width.current --format=csv
# GPUクロック情報
nvidia-smi --query-gpu=clocks.current.graphics,clocks.current.memory,clocks.max.graphics,clocks.max.memory --format=csv
# dmesgでGPU関連メッセージ
dmesg | grep -i -E "nvidia|nvrm|gpu|xid"
# InfiniBand状態確認
ibstat
ibstatus
ibv_devinfo
# RDMAデバイス確認
rdma link show
rdma resource show
# NIC状態
ethtool -i mlx5_core0
mlxlink -d /dev/mst/mt4125_pciconf0 -m
# カーネルモジュール状態
lsmod | grep nvidia
lsmod | grep mlx
lsmod | grep vfio
# NUMAトポロジ (GPU-CPUアフィニティ)
numactl --hardware
lstopo --of ascii
nvidia-smi topo -m
8-2. よくあるGPU障害(しょうがい)と解決
XID Error解釈
XID ErrorはNVIDIA GPUドライバが報告するエラーコードです。dmesgで確認できます。
| XIDコード | 意味 | 深刻度 | 対応 |
|---|---|---|---|
| XID 13 | Graphics Engine Exception | 高 | CUDAカーネルバグの可能性、ドライバ更新 |
| XID 31 | GPU Memory Page Fault | 高 | メモリアクセスエラー、コード点検 |
| XID 43 | GPU stopped processing | 高 | GPUハング、リセット必要 |
| XID 45 | Preemptive cleanup | 中 | タイムアウト、ワークロード点検 |
| XID 48 | Double Bit ECC Error | 緊急 | ハードウェア欠陥、RMA |
| XID 63 | ECC page retirement | 中 | ページ退役、累積時RMA |
| XID 64 | ECC page retirement (DBE) | 高 | Double-bitエラー、RMA検討 |
| XID 79 | GPU has fallen off the bus | 緊急 | PCIe接続切断、ハードウェア点検 |
| XID 94 | Contained ECC error | 中 | MIGインスタンス内ECCエラー |
| XID 95 | Uncontained ECC error | 緊急 | MIG隔離失敗、GPUリセット必要 |
# XIDエラーモニタリング
dmesg -w | grep "NVRM: Xid"
# 出力例:
# NVRM: Xid (PCI:0000:41:00): 79, pid=0, GPU has fallen off the bus
# NVRM: Xid (PCI:0000:41:00): 48, pid=12345, DBE (double bit error)
GPU Reset / ドライバ再ロード
# GPUハング時のリセット試行
nvidia-smi --gpu-reset -i 0
# ドライバ再ロード (すべてのGPUプロセス終了が必要)
# 1. GPU使用プロセスの確認
fuser -v /dev/nvidia*
# 2. プロセス終了
kill -9 <pid>
# 3. ドライバアンロード/ロード
sudo rmmod nvidia_uvm nvidia_drm nvidia_modeset nvidia
sudo modprobe nvidia
# 完全に解決しない場合
sudo systemctl restart nvidia-persistenced
CUDA OOMデバッグ
# PyTorchでOOM発生時のデバッグ
# メモリ使用量確認
import torch
print(f"Allocated: {torch.cuda.memory_allocated()/1e9:.2f} GB")
print(f"Reserved: {torch.cuda.memory_reserved()/1e9:.2f} GB")
print(f"Max Allocated: {torch.cuda.max_memory_allocated()/1e9:.2f} GB")
# メモリスナップショット (詳細分析)
torch.cuda.memory._record_memory_history(max_entries=100000)
# ... 学習コード実行 ...
snapshot = torch.cuda.memory._snapshot()
torch.cuda.memory._dump_snapshot("memory_snapshot.pickle")
# https://pytorch.org/memory_viz で可視化
OOM対策:
- バッチサイズ削減
- Gradient Accumulation使用
- Mixed Precision(FP16/BF16)有効化
- Gradient Checkpointing(Activation Recomputation)
- DeepSpeed ZeRO Stage 2/3適用
- モデルパラメータオフロード(CPU/NVMe)
ECCエラーとRMA手順
# ECCエラー確認
nvidia-smi --query-gpu=ecc.errors.corrected.volatile.total,ecc.errors.uncorrected.volatile.total,ecc.errors.corrected.aggregate.total,ecc.errors.uncorrected.aggregate.total --format=csv
# Retired Pages確認
nvidia-smi --query-retired-pages=gpu_uuid,retired_pages.address,retired_pages.cause --format=csv
# RMA判断基準:
# - Uncorrected (Double-bit) ECCエラーが繰り返し発生
# - Retired Pagesが閾値超過 (通常60+ pages)
# - XID 48が複数回発生
# - GPUがbusから分離 (XID 79)
Thermal Throttling対応
# 温度モニタリング
nvidia-smi --query-gpu=temperature.gpu,temperature.memory --format=csv -l 1
# 電力制限確認/設定
nvidia-smi --query-gpu=power.limit,power.default_limit,power.max_limit --format=csv
sudo nvidia-smi -pl 300 # 電力制限を300Wに設定
# クロック速度確認 (Throttling時に低下)
nvidia-smi --query-gpu=clocks.current.graphics,clocks.max.graphics --format=csv
# Throttling原因確認
nvidia-smi --query-gpu=clocks_throttle_reasons.active --format=csv
Thermal Throttling予防:
- サーバ室冷却容量の確認(GPU当たり400~1000W発熱)
- エアフロー最適化(Hot/Cold Aisle分離)
- 水冷システムの検討(DGX H100は水冷オプション対応)
- 電力制限設定(性能 vs 温度のトレードオフ)
9. 面接(めんせつ)予想質問30選
GPUアーキテクチャとCUDA(10問)
Q1. SM(Streaming Multiprocessor)の内部構造を説明し、Warp Divergenceが性能に与える影響を説明してください。
模範解答のポイント:SMはCUDA Cores、Tensor Cores、Warp Scheduler、Register File、Shared Memory/L1 Cacheで構成されます。Warp(32個のスレッド)はSIMTモデルで同一命令を実行し、if/else分岐時に両方を逐次実行するため最大2倍の性能低下が発生します。
Q2. GPUメモリ階層をRegisterからGlobal Memoryまで説明し、各々の遅延時間と最適化戦略を述べてください。
模範解答のポイント:Register(1 cycle)→ Shared Memory(5 cycles)→ L1/L2 Cache → Global Memory(HBM、600 cycles)。Shared Memoryをタイリングに活用しGlobal Memoryアクセスを削減、Memory Coalescingで帯域幅稼働率を最大化。
Q3. Memory Coalescingとは何か、なぜ重要ですか?
模範解答のポイント:Warpの32個のスレッドが連続メモリにアクセスすると1つの128-byteトランザクションに統合されます。非連続アクセス(strided)は32個の個別トランザクションに分離され、帯域幅を1/32しか活用できません。
Q4. Roofline Modelを説明し、あるカーネルがMemory-BoundかCompute-Boundかを判別する方法を述べてください。
模範解答のポイント:Arithmetic Intensity(FLOPs/Byte)を計算してハードウェアのBalance Point(Peak FLOPS / Peak BW)と比較します。H100基準では295 FLOPs/Byteが均衡点であり、これより低ければMemory-Boundです。
Q5. A100とH100の主な違いを説明し、H100のTransformer Engineが学習性能に与える影響を説明してください。
模範解答のポイント:H100はFP8対応Tensor Core(第4世代)、NVLink 4.0(900GB/s)、HBM3(3.35TB/s)、Transformer Engineを提供します。Transformer EngineはFP8とFP16を動的に切り替え、2xスループット向上を達成します。
Q6. CUDA Grid-Block-Thread階層を説明し、Blockサイズを決定する基準を述べてください。
模範解答のポイント:GridはBlockの集合、BlockはThreadの集合であり同一SMで実行されます。Blockサイズは32の倍数(Warpサイズ)、SM Occupancy最大化、Shared Memory使用量、Register使用量を考慮して決定します。通常128または256が良い出発点です。
Q7. NVIDIA Nsight SystemsとNsight Computeの違いと各々の使用シナリオを説明してください。
模範解答のポイント:Nsight Systemsはシステムレベルのタイムライン(CPU-GPU相互作用、カーネルラウンチ、メモリ転送)を表示し、Nsight Computeは個別カーネルのSM Occupancy、Memory Throughput、Warp Stall Reasonsなどを詳細分析します。
Q8. Shared MemoryのBank Conflictとは何か、どう回避しますか?
模範解答のポイント:Shared Memoryは32個のバンクで構成され、同一Warpで同じバンクに同時アクセスすると逐次処理されます。パディング(配列幅を33に)を追加するかアクセスパターンを再設計して回避します。
Q9. CUDAでHost-Deviceメモリ転送のオーバーヘッドを削減する方法を説明してください。
模範解答のポイント:Pinned Memory(cudaMallocHost)、非同期転送(cudaMemcpyAsync + CUDA Stream)、Zero-copy Memory(Unified Memory)、転送と演算のオーバーラップ、CUDA Graphを活用します。
Q10. GPU稼働率が30%しか出ない状況で、どのような順序でデバッグしますか?
模範解答のポイント:(1) nvidia-smiでメモリ/稼働率の基本確認 → (2) Nsight SystemsでCPU vs GPU時間比率分析 → (3) データロードボトルネック確認(num_workers、prefetch)→ (4) カーネルサイズ確認(バッチ増加)→ (5) 同期ボトルネック確認(CUDA Graph)→ (6) PCIeボトルネック確認。
仮想化とネットワーク(10問)
Q11. PCI Passthrough、vGPU、MIGの違いを比較し、各々の適切な使用シナリオを説明してください。
模範解答のポイント:PCI Passthroughは1:1割り当て(最大性能)、vGPUはタイムスライシング(柔軟性)、MIGは物理分割(隔離+予測性)。大規模学習はPassthrough、推論サービングのマルチテナンシーはMIG、VDI混合環境はvGPU。
Q12. IOMMUの役割とGPU仮想化における重要性を説明してください。
模範解答のポイント:IOMMU(Intel VT-d)はデバイスのDMA要求を仮想アドレスに変換してVM間メモリを隔離します。これなしではGPUが他VMのメモリにアクセスできてしまいセキュリティ問題が発生します。
Q13. MIGのプロファイル構成を説明し、A100-80GBで最大分割した場合の各インスタンスの仕様を述べてください。
模範解答のポイント:最大7個の1g.10gbインスタンスに分割可能。各々14 SM、10GB HBM2e、独立L2 Cache、別途メモリコントローラを持ちます。GI(GPU Instance)内にCI(Compute Instance)を作成してCUDAを使用可能にする必要があります。
Q14. InfiniBandとEthernetの違いを説明し、分散学習でInfiniBandが重要な理由を述べてください。
模範解答のポイント:InfiniBandはRDMAをネイティブサポートし、0.5usの遅延、CPUバイパス転送が可能です。NDRは400Gbpsの帯域幅を提供します。分散学習のAllReduce通信は数百GBのデータをやり取りするため、帯域幅と遅延が直接性能に影響します。
Q15. RDMAのZero-copy転送がどのように動作するか説明してください。
模範解答のポイント:アプリケーションがibverbs APIでメモリを登録すると、NICが当該メモリに直接DMAアクセスします。データはカーネルバッファを経由せずユーザ空間メモリからNICに直接転送されます。
Q16. GPU Direct RDMAが分散学習でどのような利点を提供しますか?
模範解答のポイント:GPUメモリからNICに直接転送し、Host Memory経由(bounce buffer)を排除します。PCIe帯域幅活用を2倍向上させ転送遅延を削減します。
Q17. RoCE v2とInfiniBandの違いを説明し、RoCE v2環境でPFC設定が重要な理由を述べてください。
模範解答のポイント:RoCE v2はUDP/IP上でRDMAを実行し、既存Ethernetインフラを活用します。ただしEthernetはパケット損失許容ベースであるため、RDMAの無損失前提のためにPFC(Priority Flow Control)で輻輳時の送信一時停止が必要です。
Q18. NCCLの役割と分散学習での動作方式を説明してください。
模範解答のポイント:NCCLは複数GPU間のAllReduce、Broadcast、AllGatherなど集合通信を最適化します。NVLink、NVSwitch、InfiniBandを自動検出して最適通信パスを選択し、Ring-AllReduceまたはTree-AllReduceアルゴリズムを使用します。
Q19. SR-IOVとは何か、GPUクラスタでどのように活用されますか?
模範解答のポイント:SR-IOVは物理NICを複数のVF(Virtual Function)に分割してVMに直接割り当てます。GPUクラスタではVM環境でInfiniBand/RoCE NICをSR-IOVで分割してGPU Direct RDMA性能を維持します。
Q20. KubeVirtでGPUをVMに割り当てる2つの方法を比較してください。
模範解答のポイント:(1) PCI Passthrough:hostDevicesで物理GPUを直接割り当て、最大性能、1:1マッピング。(2) vGPU:mediated devicesで仮想GPUを割り当て、GPU共有可能だがオーバーヘッドあり。MIG + KubeVirtの組み合わせも可能です。
K8sと性能最適化(10問)
Q21. NVIDIA GPU Operatorの構成要素を説明し、各々の役割を述べてください。
模範解答のポイント:Driver(カーネルモジュール)、Container Toolkit(ランタイム統合)、Device Plugin(K8sリソース登録)、DCGM Exporter(メトリクス)、MIG Manager(MIG自動構成)、GFD(ノードラベリング)、Validator(検証)。
Q22. K8sでGPU Scheduling時にTopology-aware schedulingがなぜ重要ですか?
模範解答のポイント:NVLinkで接続されたGPUはPCIe接続GPUより6~10倍速い通信が可能です。分散学習でGPUを任意に割り当てるとNVLinkの代わりにPCIeを経由して通信し、性能が大幅に低下します。
Q23. Gang Schedulingが分散学習で必須である理由を説明してください。
模範解答のポイント:AllReduce通信はすべてのワーカーが参加して完了します。4つ中3つのみ割り当てられると残り1つを待ちながら3つのGPUがアイドル状態になりリソースが浪費されます。Volcano/Kueueなどのスケジューラでall-or-nothing割り当てが必要です。
Q24. GPU Time-SlicingとMIGの違いをK8sの観点から説明してください。
模範解答のポイント:Time-Slicingはソフトウェアタイムスライシングで性能隔離がありませんがすべてのGPUで可能です。MIGは物理分割で完全隔離されますがA100/H100のみ対応です。K8sではそれぞれ nvidia.com/gpu replicasとnvidia.com/mig-Xg.XXgbでリクエストします。
Q25. DCGM Exporterでモニタリングすべき核心メトリクス5つと各々の意味を説明してください。
模範解答のポイント:GPU_UTIL(SM稼働率)、MEM_COPY_UTIL(メモリ帯域幅)、FB_USED(メモリ使用量)、GPU_TEMP(温度)、XID_ERRORS(ハードウェアエラー)。追加でPOWER_USAGE、ECC_SBE/DBEも重要です。
Q26. Mixed Precision Trainingの動作原理を説明し、Loss Scalingが必要な理由を述べてください。
模範解答のポイント:Forward PassをFP16で実行してTensor Coreを活用、グラディエントもFP16で計算後FP32マスター重みに適用します。FP16の表現範囲が狭いため小さなグラディエントが0に丸められることをLoss Scalingで防止します。
Q27. DeepSpeed ZeROの3つのStageを説明し、各々のメモリ削減効果を比較してください。
模範解答のポイント:Stage 1(Optimizer State分割、~1.5x)、Stage 2(+Gradient分割、~2x)、Stage 3(+Model Parameter分割、~Nx)。Stage 3は通信オーバーヘッドが最も大きいためInfiniBandなどの高速ネットワークが必須です。
Q28. Triton Inference ServerのDynamic Batchingが推論効率を高める原理を説明してください。
模範解答のポイント:個別リクエストをキューに集め、設定された最大待機時間内にバッチを構成して一括処理します。GPUはバッチが大きいほど高いスループットを示すため、動的バッチングはレイテンシとスループットのバランスを取ります。
Q29. XIDエラーのうちXID 79(「GPU has fallen off the bus」)が発生した場合のデバッグ手順を説明してください。
模範解答のポイント:(1) dmesgで前後のログ確認 → (2) PCIeリンク状態確認(lspci)→ (3) GPUリセット試行(nvidia-smi --gpu-reset)→ (4) 物理接続確認(リシーティング)→ (5) 別スロットでテスト → (6) 繰り返し発生時RMA。
Q30. 1000枚のH100 GPUクラスタを新規構築する際、GPUソフトウェアスタックをどのように設計しますか?
模範解答のポイント:(1) OS:Ubuntu 22.04 + 最新カーネル → (2) ドライバ:NVIDIA Driver 535+ → (3) ネットワーク:InfiniBand NDR + NCCL → (4) コンテナ:K8s + GPU Operator + DCGM → (5) スケジューリング:Volcano(Gang Scheduling)+ GFD(Topology-aware)→ (6) モニタリング:DCGM Exporter + Prometheus + Grafana → (7) ストレージ:GPU Direct Storage + 分散ファイルシステム → (8) MIG/vGPU:ワークロード別パーティショニング戦略策定。
10. 10ヶ月学習ロードマップ
Month 1-2: GPU基礎とCUDAプログラミング
目標: GPUアーキテクチャ理解 + CUDAプログラミング能力
| 週 | テーマ | 活動 |
|---|---|---|
| 1週 | GPUアーキテクチャ | NVIDIA GPUアーキテクチャホワイトペーパー読解(Ampere, Hopper) |
| 2週 | CUDA基礎 | ベクトル加算、行列乗算の実装 |
| 3週 | CUDA最適化 | Shared Memoryタイリング、Memory Coalescing実習 |
| 4週 | CUDA応用 | Warp-level primitives、CUDA Streams |
| 5-6週 | cuBLAS/cuDNN | ライブラリ活用、性能比較 |
| 7-8週 | プロファイリング | Nsight Systems/Computeで実際のカーネル分析 |
リソース:
- NVIDIA CUDA Programming Guide
- "Programming Massively Parallel Processors" (David Kirk, Wen-mei Hwu)
- NVIDIA DLI(Deep Learning Institute)CUDAコース
Month 3-4: Linuxシステム + GPUドライバ
目標: Linuxカーネル/ドライバレベルの理解 + GPUトラブルシューティング
| 週 | テーマ | 活動 |
|---|---|---|
| 1-2週 | Linuxカーネル基礎 | メモリ管理、デバイスドライバ、PCIe |
| 3-4週 | GPUドライバ | NVIDIAドライバのインストール/設定、モジュール構造 |
| 5-6週 | トラブルシューティング | XIDエラー分析、ECCエラー対応、dmesg分析 |
| 7-8週 | 性能ツール | perf, strace, eBPFを活用したシステム分析 |
Month 5-6: 仮想化(核心!)
目標: KVM/QEMU + PCI Passthrough + vGPU + MIG実習
| 週 | テーマ | 活動 |
|---|---|---|
| 1-2週 | KVM/QEMU | VM作成、IOMMU設定、基本仮想化 |
| 3-4週 | PCI Passthrough | GPU VFIOバインディング、VMにGPU割り当て |
| 5-6週 | MIG | MIGプロファイル構成、性能テスト |
| 7-8週 | vGPU | vGPUライセンス設定、スケジューラ比較 |
Month 7-8: ネットワーク(InfiniBand/RDMA)
目標: InfiniBandアーキテクチャ理解 + RDMAプログラミング + NCCLチューニング
| 週 | テーマ | 活動 |
|---|---|---|
| 1-2週 | InfiniBand基礎 | アーキテクチャ、Subnet Manager、基本コマンド |
| 3-4週 | RDMA | ibverbsプログラミング、ベンチマーク |
| 5-6週 | GPU Direct | GPU Direct RDMA/Storage実習 |
| 7-8週 | NCCLチューニング | 分散学習NCCLベンチマーク、環境変数最適化 |
Month 9-10: Kubernetes + 統合プロジェクト
目標: K8s GPU管理 + 大規模クラスタ運用 + ポートフォリオ完成
| 週 | テーマ | 活動 |
|---|---|---|
| 1-2週 | GPU Operator | インストール、設定、MIG Manager |
| 3-4週 | スケジューリング | Topology-aware、Gang Scheduling(Volcano) |
| 5-6週 | モニタリング | DCGM + Prometheus + Grafanaダッシュボード |
| 7-8週 | 統合プロジェクト | ポートフォリオプロジェクト完成 + 面接準備 |
11. ポートフォリオプロジェクト3選
プロジェクト1: CUDAカーネル最適化(行列乗算ベンチマーク)
目標: Naive CUDA → Shared Memory Tiling → Tensor Core活用 → cuBLAS比較
プロジェクト構成:
cuda-matmul-benchmark/
├── src/
│ ├── naive_matmul.cu # Naive実装
│ ├── tiled_matmul.cu # Shared Memoryタイリング
│ ├── wmma_matmul.cu # Tensor Core (WMMA API)
│ └── cublas_matmul.cu # cuBLASラッパー
├── benchmark/
│ ├── run_benchmarks.sh
│ └── plot_results.py # 結果可視化
├── profiles/
│ ├── nsight_systems/
│ └── nsight_compute/
└── README.md
核心成果物:
- 各実装のGFLOPS比較表
- Nsight Computeプロファイリング結果(SM Occupancy、Memory Throughput)
- cuBLAS比の達成率(通常Naive: 1
5%、Tiled: 2040%、Tensor Core: 60~80%)
プロジェクト2: MIG + K8sマルチテナントGPUクラスタ
目標: MIGを活用したGPU共有クラスタ構築
プロジェクト構成:
mig-k8s-multitenant/
├── infra/
│ ├── gpu-operator-values.yaml
│ ├── mig-config.yaml
│ └── monitoring/
│ ├── dcgm-dashboard.json # Grafanaダッシュボード
│ └── alert-rules.yaml # Prometheusアラート
├── workloads/
│ ├── inference-deployment.yaml # MIG 1g.10gb推論
│ ├── training-job.yaml # MIG 3g.40gb学習
│ └── notebook-statefulset.yaml # MIG 2g.20gb Jupyter
├── scheduler/
│ ├── gang-scheduling.yaml # Volcano設定
│ └── priority-classes.yaml
└── docs/
├── architecture.md
└── benchmark-results.md
核心成果物:
- 1枚のA100-80GBをMIGで分割して3つのワークロードを同時運用
- 各MIGインスタンスの性能隔離検証(noisy neighborテスト)
- Grafanaダッシュボード:インスタンス別GPU稼働率、メモリ、温度
プロジェクト3: 分散学習性能プロファイリング(NCCL + InfiniBand)
目標: 分散学習の通信ボトルネック分析および最適化
プロジェクト構成:
distributed-training-profiler/
├── benchmarks/
│ ├── nccl_allreduce.sh # NCCLベンチマーク
│ ├── ib_bandwidth.sh # InfiniBand帯域幅
│ └── multi_node_training.py # 実際の学習スクリプト
├── profiling/
│ ├── nsight_distributed.sh # 分散環境プロファイリング
│ └── nccl_debug_analysis.py # NCCLログ分析
├── optimization/
│ ├── nccl_env_tuning.sh # NCCL環境変数最適化
│ └── topology_optimization.py # GPU-NICトポロジ最適化
└── results/
├── scaling_efficiency.png # スケーリング効率グラフ
└── communication_breakdown.png # 通信時間分析
核心成果物:
- 2-node、4-node、8-nodeスケーリング効率測定
- NCCL AllReduce時間対演算時間比率分析
- 環境変数チューニング前後比較(NCCL_IB_HCA、NCCL_ALGOなど)
- Nsight Systemsタイムラインでの通信/演算オーバーラップ分析
12. クイズ
Q1. H100 GPUのSM 1つには何個のFP32 CUDA Coreがあり、全体のSM数はいくつですか?
正解: SM 1つに128個のFP32 CUDA Coreがあり、H100は合計132個のSMを持ちます。したがって全体のCUDA Core数は128 x 132 = 16,896個です。参考までにA100はSM当たり64個のFP32 Core x 108 SM = 6,912個です。
Q2. MIGでA100-80GBを1g.10gbプロファイルで最大分割すると何個のインスタンスが生成され、各インスタンスのSM数はいくつですか?
正解: 最大7個の1g.10gbインスタンスが生成されます。各インスタンスは約14個のSMと10GB HBM2eメモリを持ちます。各インスタンスは独立したL2 Cacheとメモリコントローラを持つため性能が物理的に隔離されます。MIGを使用するにはまずGPU Instance(GI)を作成し、その中にCompute Instance(CI)を作成してCUDAを使用可能にする必要があります。
Q3. RDMA over InfiniBandとRoCE v2の主な違い3つは何ですか?
正解: (1) 転送層: InfiniBandは独自の転送プロトコルを使用し、RoCE v2はUDP/IP上で動作します。(2) 輻輳制御: InfiniBandはCredit-basedフロー制御でネイティブ無損失ですが、RoCE v2はEthernetベースのためPFC(Priority Flow Control)設定が必須です。(3) インフラ: InfiniBandは専用スイッチ/ケーブルが必要ですが、RoCE v2は既存Ethernetスイッチを活用できコストが低いです。帯域幅はInfiniBand NDR(400Gbps)が一般的にRoCE(100~200Gbps)より高いです。
Q4. KubernetesでGang Schedulingが必要な理由を説明し、これをサポートするスケジューラを2つ以上挙げてください。
正解: 分散学習でAllReduce通信はすべてのワーカーが参加して完了します。N個のGPUのうち一部のみ割り当てられると残りを待ちながら割り当て済みGPUがアイドル状態になりリソースが浪費されます。Gang Schedulingはall-or-nothingで必要なすべてのリソースを一括割り当てします。これをサポートするスケジューラにはVolcano、Kueue(K8s SIG Scheduling)、YuniKorn(Apache)があります。デフォルトのK8sスケジューラ(kube-scheduler)はGang Schedulingをサポートしません。
Q5. GPU稼働率(SM Utilization)が90%以上なのに学習速度が遅い場合、考えられる原因3つと診断方法を説明してください。
正解: (1) Memory-Bound: SMは活発だがメモリ帯域幅が飽和した状態です。Nsight ComputeでMemory Throughputがピークに近いか確認します。Shared Memory活用、Memory Coalescingパターンを点検します。(2) Warp Divergence: 条件分岐によりWarp内スレッドが逐次実行されます。Nsight ComputeでBranch Efficiencyメトリクスを確認します。(3) Low SM Occupancy + 高Compute: 少数のWarpが高い算術強度で実行中です。Active Warps per SMを確認しBlockサイズ、Register使用量を調整します。追加でTensor Core未活用(FP16/BF16を使用していない)も原因となり得ます。
13. 参考資料(さんこうしりょう)
公式ドキュメント
- NVIDIA CUDA Programming Guide - NVIDIA Developer
- NVIDIA A100 Whitepaper - NVIDIA
- NVIDIA H100 Whitepaper - NVIDIA
- NVIDIA MIG User Guide - NVIDIA Developer
- NVIDIA Virtual GPU Software Documentation - NVIDIA
- NVIDIA GPU Operator Documentation - NVIDIA
- NVIDIA DCGM Documentation - NVIDIA
- NVIDIA NCCL Documentation - NVIDIA
ネットワーク
- InfiniBand Architecture Specification - IBTA
- RDMA Aware Programming User Manual - NVIDIA Networking (Mellanox)
- RoCE v2 Deployment Guide - NVIDIA Networking
Kubernetes
- NVIDIA Device Plugin for Kubernetes - GitHub
- Volcano: Kubernetes Native Batch System - volcano.sh
- Kueue: Kubernetes-native Job Queueing - K8s SIG Scheduling
学習/推論最適化
- DeepSpeed Documentation - Microsoft
- Triton Inference Server Documentation - NVIDIA
- vLLM Documentation - vLLM Project
- Flash Attention Paper - Tri Dao et al.
書籍
- "Programming Massively Parallel Processors" - David Kirk, Wen-mei Hwu
- "CUDA by Example" - Jason Sanders, Edward Kandrot
- "Computer Architecture: A Quantitative Approach" - Hennessy, Patterson
- "Understanding Linux Kernel" - Daniel P. Bovet, Marco Cesati
コミュニティ/ブログ
- NVIDIA Developer Blog - developer.nvidia.com/blog
- NVIDIA GTC Sessions (無料) - nvidia.com/gtc
- Horace He's "Making Deep Learning Go Brrrr" Blog Series
- Lily Chen's GPU Mode Community - Discord