Skip to content
Published on

GPU Software Engineer 합격 가이드: CUDA 아키텍처부터 vGPU/MIG, InfiniBand, K8s GPU 스케줄링까지 시스템 최적화 완전 정복

Authors

1. GPU Software Engineer라는 희소한 커리어

"GPU를 쓰는 사람" vs "GPU가 일하게 만드는 사람"

2024년 이후 AI 업계를 관통하는 키워드는 "GPU"입니다. 모든 기업이 GPU를 확보하기 위해 사투를 벌이고 있지만, 정작 확보한 GPU를 제대로 운용할 수 있는 엔지니어는 극소수입니다.

여기서 결정적 구분이 필요합니다:

구분GPU를 쓰는 사람GPU가 일하게 만드는 사람
역할ML Engineer, ResearcherGPU Software Engineer
관심사모델 정확도, 학습 알고리즘GPU 활용률, 메모리 대역폭, 스케줄링
사용 도구PyTorch, TensorFlownvidia-smi, Nsight, DCGM, NCCL
주요 질문"이 모델 성능이 왜 안 나오지?""이 GPU가 왜 70%만 쓰이고 있지?"
추상화 레벨Python APICUDA 커널, 드라이버, 하이퍼바이저
대응 영역모델 아키텍처 변경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유플러스 GPU기술 TF의 미션

LG유플러스가 GPU기술 TF를 신설한 배경을 이해해야 합니다:

  1. 통신사의 AI 인프라 사업: LG유플러스는 자체 AI 서비스뿐 아니라, 기업 고객에게 GPU 클라우드를 제공하는 사업을 추진하고 있습니다.
  2. GPU 멀티테넌시: 한 장의 GPU를 여러 고객이 나눠 쓰게 하려면 vGPU/MIG 기술이 필수입니다.
  3. 네트워크 강점 활용: 통신사로서 InfiniBand/RoCE 고속 네트워크 설계에 대한 역량이 있습니다.
  4. 엔드-투-엔드 최적화: 하드웨어 선정부터 가상화, 컨테이너, AI 워크로드 온보딩까지 전 구간을 책임질 팀입니다.

관련 직군 비교

직군핵심 역량GPU 깊이인프라 깊이
ML Engineer모델 개발, 학습 파이프라인낮음 (API 수준)낮음
MLOps EngineerCI/CD, 모델 서빙, 파이프라인 자동화중간중간
GPU SW EngineerGPU 아키텍처, 가상화, 드라이버매우 높음높음
Infra SRE서버/네트워크 가용성, 모니터링중간매우 높음
HPC Engineer병렬 컴퓨팅, MPI, 스케줄러높음높음

GPU Software Engineer는 이 모든 직군의 교차점에 위치하며, 특히 하드웨어에 가장 가까운 소프트웨어 레이어를 담당합니다.


2. JD 라인 바이 라인 해부

LG유플러스 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: SM128FP32 코어
├── Tensor Cores
│   └── H100: SM4세대 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 수108132192
CUDA Cores6,91216,89621,760+
Tensor Cores432 (3세대)528 (4세대)768 (5세대)
메모리HBM2e 80GBHBM3 80GBHBM3e 192GB
메모리 대역폭2.0 TB/s3.35 TB/s8.0 TB/s
NVLink3.0 (600GB/s)4.0 (900GB/s)5.0 (1.8TB/s)
Transformer Engine없음FP8 지원FP4 지원
MIG 지원최대 7 인스턴스최대 7 인스턴스최대 7 인스턴스
TDP400W700W1000W
FP16 Tensor 성능312 TFLOPS989 TFLOPS2,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 BytesO(N)N이 크면 Compute-Bound
- Transformer Attention: 보통 Memory-Bound (특히 추론 시)

Memory Coalescing (메모리 병합 접근):

Warp의 32개 스레드가 연속 메모리를 접근하면, 하드웨어가 이를 하나의 큰 트랜잭션으로 병합합니다. 비연속 접근은 여러 트랜잭션으로 분리되어 대역폭 낭비가 발생합니다.

// 좋은 예: 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 0Bank 0 (addr 0)
Thread 1Bank 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
cuFFTFast Fourier TransformcufftExecC2C
cuSPARSE희소 행렬 연산cusparseSpMV
ThrustC++ 병렬 알고리즘 (STL-like)thrust::sort, thrust::reduce
CUTLASSGEMM 커스터마이징템플릿 기반 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 Hypervisor

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유플러스 환경에서는 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 0VFIO 드라이버 바인딩 → VM1 (직접 접근)
├── GPU 1VFIO 드라이버 바인딩 → VM2 (직접 접근)
├── GPU 2NVIDIA 드라이버 → Host 사용
└── GPU 3NVIDIA 드라이버 → 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)로 하나의 물리 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-seriesVirtual ApplicationA100-1-5A (5GB, VDI 앱)
B-seriesVirtual PCA100-2-10B (10GB, VDI 데스크탑)
C-seriesComputeA100-4-20C (20GB, AI 연산)
Q-seriesQuadroA100-8-40Q (40GB, 전문 그래픽)

LG유플러스 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 비교

특성MIGvGPU
격리 수준물리적 (SM + 메모리 완전 분리)시간 분할 (소프트웨어 격리)
성능 예측일정함 (전용 리소스)변동 가능 (다른 VM 영향)
최대 인스턴스7개 (A100/H100)GPU 메모리 한도 내 다수
지원 GPUA100, 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 1VM2
├── VF 2VM3
└── ... (최대 128VF)

장점:
- 가상 브릿지 없이 VMNIC에 직접 접근
- 네이티브에 가까운 네트워크 성능
- CPU 오버헤드 최소화

GPU Direct RDMA 조합:
VMGPU ←→ VF(SR-IOV NIC) ←→ InfiniBand ←→ 원격 GPU
   (PCIe 직접)  (SR-IOV 바이패스)  (RDMA)

4-6. KubeVirt

KubeVirt는 Kubernetes 위에서 VM을 1등급 리소스로 관리합니다. 컨테이너와 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 NDRRoCE v2 (100GbE)TCP/IP (100GbE)
대역폭400 Gbps100 Gbps100 Gbps
지연 시간0.5us1~2us10~50us
RDMA 지원네이티브RoCE v2없음 (커널 경유)
CPU 오버헤드거의 없음낮음높음
혼잡 제어Credit-basedPFC/ECNTCP 혼잡 제어
비용매우 높음중간낮음
사용처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]
├── HCAServer 2 [GPU 0~7]
├── HCAServer 3 [GPU 0~7]
└── HCAServer 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 전송 (기존):
AppSocket APITCP/IP Stack (커널)NIC DriverNIC → 네트워크
CPU 개입 (복사, 체크섬, 세그먼테이션)

RDMA 전송:
AppRDMA VerbsNIC (직접) → 네트워크
Zero-copy, CPU 바이패스

RDMA 전송 유형

전송 타입설명사용 사례
InfiniBand네이티브 RDMAHPC, AI 클러스터
RoCE v2RDMA over UDP/IP클라우드 환경
iWARPRDMA 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 없이):
GPU0PCIeHost MemoryNIC → 네트워크 → NICHost MemoryPCIeGPU1
       (복사1)              (복사2)         (복사3)              (복사4)

GPU Direct RDMA:
GPU0PCIeNIC → 네트워크 → NICPCIeGPU1
       (직접)                        (직접)
CPU 바이패스, 복사 횟수 2배 감소

GPU Direct Storage (GDS)

일반 스토리지 접근:
NVMeHost Memory (bounce buffer)GPU Memory
       CPU 개입, 2번 복사

GPU Direct Storage:
NVMeGPU 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 Scheduling

기본 스케줄링

K8s의 기본 GPU 스케줄링은 단순합니다: Pod이 요청한 GPU 수만큼 사용 가능한 노드에 배치합니다. 하지만 대규모 GPU 클러스터에서는 더 정교한 스케줄링이 필요합니다.

Topology-Aware Scheduling

DGX H100 GPU 토폴로지:
GPU0NVLinkGPU1 (같은 NVSwitch 도메인)
GPU2NVLinkGPU3 (같은 NVSwitch 도메인)
GPU4NVLinkGPU5 (같은 NVSwitch 도메인)
GPU6NVLinkGPU7 (같은 NVSwitch 도메인)

GPU0PCIeGPU4 (다른 도메인, 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. GPU 모니터링 on K8s

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 지원사용처
FP3232기준O (낮은 처리량)기본 학습
TF3219-O (A100+)자동 적용
FP16162xOMixed Precision
BF16162xO (A100+)LLM 학습 (더 넓은 범위)
FP8 (E4M3)84xO (H100+)Transformer Engine
INT884xO추론 양자화

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등분하여 NGPU에서 동일 모델 학습
AllReduce로 그래디언트 동기화
→ 통신량: O(model_size)

Tensor Parallelism:
하나의 레이어(행렬)N등분하여 NGPU에 분배
Forward/Backward 각 레이어마다 통신 필요
GPU 간 고속 통신(NVLink) 필수

Pipeline Parallelism:
모델의 레이어를 N등분하여 NGPU에 순차 배치
→ 마이크로배치를 파이프라인으로 처리
버블(유휴 시간) 최소화가 핵심

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 아키텍처:
ClientHTTP/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 ComputeMemory Throughput 확인
   │   │   └── Memory Coalescing 패턴 점검
   │   └── Warp Divergence 가능성
   │       └── Nsight ComputeWarp 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 13Graphics Engine Exception높음CUDA 커널 버그 가능, 드라이버 업데이트
XID 31GPU Memory Page Fault높음메모리 접근 오류, 코드 점검
XID 43GPU stopped processing높음GPU hang, 리셋 필요
XID 45Preemptive cleanup중간타임아웃, 워크로드 점검
XID 48Double Bit ECC Error긴급하드웨어 결함, RMA
XID 63ECC page retirement중간페이지 은퇴, 누적 시 RMA
XID 64ECC page retirement (DBE)높음Double-bit 에러, RMA 고려
XID 79GPU has fallen off the bus긴급PCIe 연결 끊김, 하드웨어 점검
XID 94Contained ECC error중간MIG 인스턴스 내 ECC 에러
XID 95Uncontained 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 hang 시 리셋 시도
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 대처:

  1. 배치 크기 줄이기
  2. Gradient Accumulation 사용
  3. Mixed Precision (FP16/BF16) 활성화
  4. Gradient Checkpointing (Activation Recomputation)
  5. DeepSpeed ZeRO Stage 2/3 적용
  6. 모델 파라미터 오프로딩 (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개 스레드가 연속 메모리를 접근하면 하나의 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에 할당하는 두 가지 방법을 비교하세요.

모범 답변 포인트: (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/QEMUVM 생성, IOMMU 설정, 기본 가상화
3-4주PCI PassthroughGPU VFIO 바인딩, VM에 GPU 할당
5-6주MIGMIG 프로필 구성, 성능 테스트
7-8주vGPUvGPU 라이선스 설정, 스케줄러 비교

Month 7-8: 네트워크 (InfiniBand/RDMA)

목표: InfiniBand 아키텍처 이해 + RDMA 프로그래밍 + NCCL 튜닝

주차주제활동
1-2주InfiniBand 기초아키텍처, Subnet Manager, 기본 명령어
3-4주RDMAibverbs 프로그래밍, 벤치마크
5-6주GPU DirectGPU 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: 15%, 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개의 SM10GB 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. 참고 자료

공식 문서

  1. NVIDIA CUDA Programming Guide - NVIDIA Developer
  2. NVIDIA A100 Whitepaper - NVIDIA
  3. NVIDIA H100 Whitepaper - NVIDIA
  4. NVIDIA MIG User Guide - NVIDIA Developer
  5. NVIDIA Virtual GPU Software Documentation - NVIDIA
  6. NVIDIA GPU Operator Documentation - NVIDIA
  7. NVIDIA DCGM Documentation - NVIDIA
  8. NVIDIA NCCL Documentation - NVIDIA

네트워크

  1. InfiniBand Architecture Specification - IBTA
  2. RDMA Aware Programming User Manual - NVIDIA Networking (Mellanox)
  3. RoCE v2 Deployment Guide - NVIDIA Networking

Kubernetes

  1. NVIDIA Device Plugin for Kubernetes - GitHub
  2. Volcano: Kubernetes Native Batch System - volcano.sh
  3. Kueue: Kubernetes-native Job Queueing - K8s SIG Scheduling

학습/추론 최적화

  1. DeepSpeed Documentation - Microsoft
  2. Triton Inference Server Documentation - NVIDIA
  3. vLLM Documentation - vLLM Project
  4. Flash Attention Paper - Tri Dao et al.

서적

  1. "Programming Massively Parallel Processors" - David Kirk, Wen-mei Hwu
  2. "CUDA by Example" - Jason Sanders, Edward Kandrot
  3. "Computer Architecture: A Quantitative Approach" - Hennessy, Patterson
  4. "Understanding Linux Kernel" - Daniel P. Bovet, Marco Cesati

커뮤니티/블로그

  1. NVIDIA Developer Blog - developer.nvidia.com/blog
  2. NVIDIA GTC Sessions (무료) - nvidia.com/gtc
  3. Horace He's "Making Deep Learning Go Brrrr" Blog Series
  4. Lily Chen's GPU Mode Community - Discord