학습(Training) 테스트는 추론(vLLM)과 달리 역전파(Backpropagation) 계산, 가중치/옵티마이저 상태 저장, GPU 간 대규모 올리듀스(All-Reduce) 집합 통신이 발생하므로 하드웨어의 한계를 검증하는 가장 확실한 방법입니다.
단일 노드(B300 8-GPU) 환경에서 NVLink 대역폭, VRAM 무결성, 풀로드 전력 소모를 온전히 검증하기 위한 학습 테스트 전략 3가지를 정리했습니다.
복잡도와 목적에 따라 아래 3가지 중 하나를 선택하는 것이 표준입니다.
| 도구 | 특징 및 목적 | 구현 난이도 | 에어갭 적합성 |
|---|---|---|---|
| ① PyTorch Distributed / NCCL All-Reduce | 통신 및 텐서 연산 베이스라인 (더미 데이터) | 매우 낮음 | 최상 (추가 다운로드 0) |
| ② DeepSpeed / Hugging Face Trainer (LoRA) | 실제 70B 모델 Fine-Tuning 파이프라인 검증 | 중간 | 높음 (사전 확보한 70B 활용) |
| ③ Megatron-Core / NeMo | B300 풀 스펙 Pre-training (Tensor/Pipeline 병렬) | 높음 | 중간 |
인수 시험(Acceptance Test) 및 하드웨어 안정성 검증 목적이라면 ①번(PyTorch NCCL 벤치마크)과 ②번(가벼운 LoRA 파인튜닝) 조합이 가장 깔끔합니다.
외부에서 추가 데이터셋이나 복잡한 프레임워크를 받을 필요 없이, NVIDIA PyTorch 공식 컨테이너(nvcr.io/nvidia/pytorch:latest) 하나만 있으면 단 5분 만에 B300 8장을 100% 풀로드로 태우며 통신 이상 여부를 잡을 수 있습니다.
train_synthetic.py)더미 LLM 레이어를 생성하여 Forward Backward Optimizer Step을 무한 반복하는 스크립트입니다.
import os
import torch
import torch.nn as nn
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP
def setup():
dist.init_process_group("nccl")
local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(local_rank)
return local_rank
def cleanup():
dist.destroy_process_group()
def run_synthetic_training():
local_rank = setup()
# B300 VRAM을 채우기 위한 대형 선형 계층 모델 (약 10B 규모 파라미터 모사)
layers = [nn.Linear(8192, 8192, bias=False).cuda(local_rank) for _ in range(8)]
model = nn.Sequential(*layers)
model = DDP(model, device_ids=[local_rank])
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)
loss_fn = nn.MSELoss()
# 합성 데이터 생성 (Forward & Backward)
batch_size = 64
seq_len = 2048
inputs = torch.randn(batch_size, 8192, device=local_rank, dtype=torch.float32)
targets = torch.randn(batch_size, 8192, device=local_rank, dtype=torch.float32)
print(f"[Rank {local_rank}] Training benchmark started...")
for step in range(100):
optimizer.zero_grad()
outputs = model(inputs)
loss = loss_fn(outputs, targets)
loss.backward() # 역전파 시 8개 GPU 간 All-Reduce 발생
optimizer.step()
if local_rank == 0 and step % 10 == 0:
print(f"Step {step}/100 - Loss: {loss.item():.4f}")
cleanup()
if __name__ == "__main__":
run_synthetic_training()
podman run --rm -it --privileged \
--device nvidia.com/gpu=all \
--ipc=host \
--net=host \
-v $(pwd)/train_synthetic.py:/workspace/train_synthetic.py:ro \
nexus.internal:8082/nvidia/pytorch:latest \
torchrun --nproc_per_node=8 /workspace/train_synthetic.py
이미 앞서 확보해 둔 Llama-3.1-70B-Instruct 가중치와 ShareGPT 데이터를 그대로 재활용하여 Hugging Face의 TRL (SFTTrainer) 또는 PEFT (LoRA)로 학습 파이프라인을 검증하는 방식입니다.
peft, bitsandbytes, trl, accelerate (Hugging Face 생태계 기본 학습 툴킷)vllm 컨테이너에는 학습 툴킷이 없으므로 pytorch 기본 컨테이너를 쓰거나 가상환경에 해당 라이브러리를 반입해야 합니다.)accelerate_config.yaml)8개 GPU에 70B 모델의 그래디언트와 옵티마이저를 샤딩하여 VRAM OOM 없이 학습을 수행합니다.
compute_environment: LOCAL_MACHINE
distributed_type: FSDP
fsdp_config:
fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP
fsdp_backward_prefetch: BACKWARD_PRE
fsdp_offload_params: false
fsdp_sharding_strategy: FULL_SHARD # ZeRO-3 형태
mixed_precision: bf16
num_processes: 8
accelerate launch --config_file accelerate_config.yaml train_lora.py \
--model_name_or_path /data/models/Llama-3.1-70B-Instruct \
--dataset_name /data/datasets/ShareGPT_V3_unfiltered_cleaned_split.json \
--output_dir /data/checkpoints/test-lora \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 4 \
--max_steps 50 \
--bf16 True
학습이 돌아가는 동안 터미널 창을 분할하여 아래 항목들을 집중 모니터링합니다.
watch -n 0.5 'nvidia-smi nvlink -g 0 -s' (Tx/Rx 카운터 급증 확인)nvidia-smi --query-gpu=power.draw,temperature.gpu --format=csv -l 1safetensors)를 디스크나 MinIO AIStor로 덤프할 때 로컬 NVMe 및 네트워크 버스에 병목이 생기지 않는지 확인.nvcr.io/nvidia/pytorch:latest (또는 최신 태그) 이미지 1개만 MacBook에서 추가로 다운로드(docker save)해 두시면 됩니다.torchrun --nproc_per_node=8로 30분~1시간 구동하여 B300의 연산/통신/전력 3박자 하드웨어 무결성을 최종 합격 판정하시면 됩니다.===
전반적으로 잘 정리되어 있습니다. 다만 Blackwell(B300/GB300) + RHEL(EL) Bare Metal 기준으로는 몇 가지를 보완하는 것이 NVIDIA의 최신 공식 문서와 더 일치합니다.
제시하신 문서는 모두 맞습니다.
특히 Blackwell(HGX B200/B300, GB200/GB300 계열)에서는 Fabric Manager Guide를 반드시 함께 참고해야 합니다. (NVIDIA Docs)
"B300은 R570 이상"이라는 내용은 맞습니다.
NVIDIA 공식 문서에서는
를 요구합니다. (NVIDIA Docs)
현재 절차에서 가장 수정해야 하는 부분입니다.
현재 문서에는
dnf module install nvidia-driver:latest-dkms
로 되어 있는데,
Blackwell HGX(B200/B300)에서는 NVIDIA가 Open Kernel Module(OpenRM) 설치를 권장합니다.
공식 예시는
sudo dnf module install nvidia-driver-570-open
sudo dnf install nvlink-570
입니다. (NVIDIA Docs)
즉 Blackwell에서는
세트 설치가 권장됩니다.
현재 절차에는 Fabric Manager만 포함되어 있는데,
최신 HGX B200/B300는 4세대 NVSwitch(NVLink5)를 사용하므로 추가 구성 요소가 필요합니다.
공식 문서에서는
Driver
↓
NVLink5 package
↓
Fabric Manager
↓
NVLSM
구성이 요구됩니다. (NVIDIA Docs)
즉
dnf install nvlink-570
또는 해당 Driver Branch의 NVLink 패키지가 함께 설치되어야 합니다.
아주 중요한 내용인데,
Driver == Fabric Manager
버전이 정확히 동일해야 합니다.
예를 들어
Driver 570.211.01
Fabric Manager 570.211.01
처럼 맞춰야 하며,
Release Note에서도 항상 동일 버전으로 제공됩니다. (NVIDIA Docs)
HGX B200/B300에서는 NVIDIA가 추가적으로 다음 패키지를 요구합니다.
예)
rdma-core
libibumad
infiniband-diags
또는
환경을 사용할 수도 있습니다.
Fabric Manager Guide에도 HGX B200/B300에서는 InfiniBand 관련 패키지가 필요하다고 명시되어 있습니다. (NVIDIA Docs)
Blackwell에서는 커널 요구사항이 있습니다.
공식 문서 기준
Linux Kernel 5.17+
또는 NVIDIA가 제공하는 Backport Patch가 적용된 커널을 사용해야 합니다. (NVIDIA Docs)
RHEL10은 문제가 없지만,
RHEL9 계열에서는 사용 중인 커널 버전을 반드시 확인하는 것이 좋습니다.
추가하면 좋은 검증 명령입니다.
nvidia-smi
nv-fabricmanager -v
systemctl status nvidia-fabricmanager
systemctl status nvidia-persistenced
nvidia-smi topo -m
nvidia-smi nvlink -s
또는
systemctl status nvlsm
도 함께 확인하는 것이 좋습니다.
최신 NVIDIA 권장 절차를 요약하면 다음과 같습니다.
nvidia-persistenced 활성화nvidia-fabricmanager 활성화nvidia-smi 및 NVLink 토폴로지 확인현재 작성하신 절차는 약 90~95% 수준으로 정확합니다. 다만 최신 Blackwell(HGX B200/B300, GB300) 기준으로는 다음 항목을 반영하면 NVIDIA 공식 가이드와 거의 동일한 수준이 됩니다.
latest-dkms 대신 Open Driver(nvidia-driver-570-open 이상) 사용nvlink-570(또는 해당 드라이버 브랜치의 NVLink 패키지) 설치 추가===
맞습니다. vLLM은 기본적으로 inference/serving benchmark 용도라서, B300/GB300의 학습 성능을 검증하려면 별도의 training workload를 구성하는 게 좋습니다.
특히 지금 구축하려는 환경이 B300 8-GPU + RHEL + Kubernetes + RDMA/NCCL이라면, 단순히 "모델이 학습된다"를 보는 것보다 GPU → NVLink/NVSwitch → NCCL → RDMA → multi-node scaling을 단계적으로 검증하는 것이 중요합니다.
NVIDIA도 B300의 실제 training 성능을 MLPerf Training으로 측정하고 있고, 최신 MLPerf 6.0에는 8×B300에서 Llama 2 70B LoRA 결과가 공개되어 있습니다. (NVIDIA Developer)
B300 Training Validation
│
┌────────────────┼────────────────┐
│ │ │
Level 1 Level 2 Level 3
GPU/Framework Single Node Multi Node
│ │ │
PyTorch CUDA 8× B300 2× B300 Node
│ │ │
GEMM/FP8 Llama LoRA NCCL/RDMA
│ │
└───────┬────────┘
│
Level 4
실제 Training E2E
│
NeMo / Megatron
Pretraining/SFT
먼저 모델 학습을 하지 말고 PyTorch training microbenchmark를 돌리는 게 좋습니다.
예를 들어:
등입니다.
여기서 확인할 것은:
| 항목 | 측정 |
|---|---|
| GPU utilization | >95% |
| GPU memory BW | 실제 사용률 |
| Tensor Core | 활성화 |
| BF16/FP8 throughput | TFLOPS |
| forward | ms |
| backward | ms |
| optimizer | ms |
이 단계는 GPU/driver/CUDA/PyTorch 문제와 모델/분산학습 문제를 분리하는 데 중요합니다.
여기부터 실제 training을 합니다.
제가 가장 추천하는 것은 Llama 2 70B LoRA/PEFT입니다.
NVIDIA 자체 MLPerf Training 6.0에서도 B300 8GPU에 대해:
Llama2-70B-Lora
를 실제 benchmark workload로 사용하고 있습니다. (NVIDIA Developer)
따라서 B300 검증용으로 상당히 좋은 기준점입니다.
다만 처음부터 70B를 돌릴 필요는 없습니다.
1B
↓
7B
↓
13B
↓
70B LoRA
로 가는 것을 추천합니다.
예를 들어 처음에는:
Llama 3.1 8B
BF16
batch size 1~8
sequence length 4096
정도로 시작합니다.
그 다음:
Llama 2 70B
LoRA
8 × B300
으로 올라갑니다.
Inference에서는
tokens/sec
requests/sec
TTFT
TPOT
를 보지만,
Training에서는 다음을 봐야 합니다.
training throughput
= tokens / sec / GPU
step time
= sec / step
samples/sec
GPU utilization
GPU memory utilization
MFU
특히 중요한 것이:
Model FLOPs Utilization
입니다.
예를 들어 B300의 이론적 Tensor Core 성능 대비 실제 training에서 얼마나 활용하는지를 봅니다.
따라서 단순히
nvidia-smi
GPU-Util = 99%
라고 해서 좋은 training이라고 볼 수 없습니다.
이게 사용자 환경에서는 아주 중요합니다.
8×B300이면 GPU 하나의 성능보다
GPU
↓
NVLink
↓
NVSwitch
↓
NCCL
이 제대로 작동하는지가 중요합니다.
PyTorch 역시 CUDA GPU distributed training에는 NCCL을 권장하고 있으며, Ethernet 환경에서도 NCCL을 distributed GPU training의 기본 backend로 권장합니다. (PyTorch Documentation)
먼저 실제 모델 없이:
nccl-tests
를 돌립니다.
예:
all_reduce_perf
all_gather_perf
reduce_scatter_perf
broadcast_perf
1 GPU
2 GPU
4 GPU
8 GPU
를 각각 측정합니다.
특히
1 → 2
2 → 4
4 → 8
의 scaling을 봅니다.
사용자 환경에서는 제가 오히려 이 부분을 vLLM inference보다 더 중요하게 보겠습니다.
예를 들어:
Node 1
├─ GPU0~7
│
└─ NVSwitch
Node 2
├─ GPU0~7
│
└─ NVSwitch
그리고
Node1 GPU
│
│ NCCL
│
▼
RDMA NIC
│
│ RoCEv2
│
▼
RDMA NIC
│
▼
Node2 GPU
를 검증합니다.
여기에서 사용자의 기존 환경인
E810
25Gb × 2
bond1
Cilium
BGP
ECMP
RoCE/RDMA
와 직접 연결됩니다.
제가 실제 POC라면 다음처럼 구성하겠습니다.
| Test | GPU | Workload | 목적 |
|---|---|---|---|
| T1 | 1 | PyTorch microbenchmark | GPU/CUDA |
| T2 | 8 | Llama 8B | NVLink/NVSwitch |
| T3 | 8 | Llama 70B LoRA | 실제 training |
| T4 | 16+ | Llama/NeMo | NCCL/RDMA scaling |
그리고 T4가 특히 중요합니다.
저라면 PyTorch → NeMo 순서로 갑니다.
PyTorch
+ NCCL
+ Transformer
먼저 infrastructure를 검증합니다.
NVIDIA NeMo
+ Megatron-Core
+ NCCL
실제 LLM training을 검증합니다.
NVIDIA의 NeMo는 현재 pretraining, post-training, RL 등을 지원하고 있고, pretraining recipe도 제공합니다. (NVIDIA Docs)
예를 들어 NeMo에서는:
nemo llm pretrain --factory llama3_8b
와 같은 형태로 pretraining을 시작할 수 있습니다. (NVIDIA Docs)
Fine-tuning은:
nemo llm finetune
방식으로 수행할 수 있습니다. (NVIDIA Docs)
이것도 중요합니다.
random initialization
↓
dataset
↓
forward
↓
backward
↓
optimizer
가장 무겁습니다.
GPU/RDMA 성능 검증에는 최고지만 비용이 큽니다.
기존 모델을 가져와서
모든 parameter
를 업데이트합니다.
Training infrastructure 검증에 좋습니다.
base model frozen
+
LoRA adapter training
입니다.
비교적 작은 자원으로 실제 LLM training pipeline을 검증할 수 있습니다.
NVIDIA도 SFT와 PEFT를 별도의 customization 방법으로 제공하며, PEFT는 trainable parameter를 크게 줄이는 방식입니다. (NVIDIA Docs)
POC에서는 LoRA → Full FT → Pretraining 순서를 추천합니다.
이게 Blackwell에서 상당히 중요합니다.
단순히
BF16 training
만 하면 B300의 장점을 충분히 검증하지 못합니다.
최소한:
BF16
FP8
두 가지를 비교하세요.
예:
| Test | Precision |
|---|---|
| Baseline | BF16 |
| Optimization | FP8 |
| Advanced | FP8 + Transformer Engine |
그리고 비교:
tokens/sec
step time
GPU utilization
memory usage
MFU
loss convergence
까지 봅니다.
Training benchmark에서 가장 중요한 함정입니다.
예를 들어:
FP8
↓
100k tokens/sec
가
BF16
↓
70k tokens/sec
보다 빠르다고 해서 무조건 성공은 아닙니다.
동일한 quality target에 도달해야 합니다.
MLPerf Training도 단순 throughput만 비교하지 않고 quality target을 함께 정의합니다. NVIDIA의 현재 B300 결과에서도 Llama2-70B LoRA에 eval-loss quality target을 사용합니다. (NVIDIA Developer)
따라서:
Performance
+
Convergence
+
Correctness
세 가지를 같이 봐야 합니다.
현재 구축하려는 환경을 고려하면 저는 다음 test matrix를 추천합니다.
B300 Training POC
│
┌─────────────────┼──────────────────┐
│ │ │
GPU Test Single Node Multi Node
│ │ │
CUDA/FP8/BF16 8× B300 16× B300
│ │ │
│ Llama 8B NCCL
│ Llama 70B LoRA RDMA
│ │ │
└─────────────────┼──────────────────┘
│
E2E Training
│
NeMo/Megatron
│
┌─────────┴─────────┐
│ │
BF16 FP8
│ │
convergence convergence
T1
1 GPU
PyTorch
BF16/FP8
↓
T2
8 GPU
Llama 8B
BF16
↓
T3
8 GPU
Llama 70B LoRA
BF16 / FP8
↓
T4
2 nodes × 8 GPU
NCCL
RoCE/RDMA
↓
T5
NeMo/Megatron
real training
순서가 가장 좋습니다.
사용자 환경에서는 단순한 GPU training benchmark보다 "GPU → RDMA → AIStor"까지 연결한 training E2E가 상당히 가치 있습니다.
예를 들어:
┌─────────────┐
│ AIStor │
│ Training │
│ Dataset │
└──────┬──────┘
│
RDMA
│
┌──────▼──────┐
│ B300 Node 1 │
│ 8 × B300 │
└──────┬──────┘
│
NCCL/RDMA
│
┌──────▼──────┐
│ B300 Node 2 │
│ 8 × B300 │
└─────────────┘
이렇게 하면 단순 GPU benchmark가 아니라 실제 AI training infrastructure 검증이 됩니다.
그리고 이 경우에는
AIStor read throughput
GPU utilization
DataLoader wait
CPU utilization
PCIe
NVLink
NCCL
RDMA bandwidth
RDMA retransmission
NIC utilization
training step time
을 동시에 수집하면 좋습니다.
결론적으로 vLLM은 "Inference validation"으로 두고, Training은 PyTorch/NCCL → Llama LoRA → NeMo/Megatron → Multi-node RDMA → AIStor E2E의 5단계로 별도 구성하는 것을 추천합니다. NVIDIA가 B300의 실제 training benchmark에서도 Llama 2 70B LoRA를 사용하고 있으므로, POC의 대표 workload로 삼기에도 상당히 좋습니다. (NVIDIA Developer)
원하시면 다음 단계로 현재 말씀하신 "RHEL 10.2 + B300 8장 + E810/RDMA + Kubernetes" 환경에 맞춰서, 실제 실행 가능한 Training POC를 T1~T8 테스트 케이스별로 명령어/컨테이너/모델/데이터 크기/NCCL 설정/Prometheus 지표/PASS-FAIL 기준까지 포함한 표준 테스트 계획으로 만들어드릴 수 있습니다.
===
좋습니다. 지금까지 말씀하신 환경을 기준으로 "B300 8-GPU 베어메탈 → Kubernetes → multi-node → RDMA → AIStor dataset"까지 실제로 검증할 수 있는 Training POC T1~T8 표준안으로 잡겠습니다.
전제는 다음과 같습니다.
현재 NVIDIA GPU Operator 공식 지원표에서도 RHEL 10.2 + Kubernetes 1.33~1.37 조합이 지원 대상으로 명시되어 있습니다. (NVIDIA Docs)
| ID | 테스트 | GPU | 핵심 검증 |
|---|---|---|---|
| T1 | GPU/CUDA Sanity | 1 | Driver/CUDA/B300 |
| T2 | GPU Compute | 1 | BF16/FP8 Tensor Core |
| T3 | GPU-GPU Fabric | 8 | NVLink/NVSwitch |
| T4 | Single-node NCCL | 8 | NCCL + NVSwitch |
| T5 | LLM Training | 8 | Llama 3.1 8B |
| T6 | Large Model LoRA | 8 | Llama 3.1 70B |
| T7 | Multi-node Training | 16+ | NCCL + RDMA |
| T8 | E2E Training | 16+ | AIStor → GPU → NCCL/RDMA |
이 순서가 중요한 이유는 실패 원인을 계층별로 격리할 수 있기 때문입니다.
가능하면 host에 PyTorch/NeMo를 직접 설치하지 말고 NVIDIA CUDA 기반 training container를 사용하세요.
예를 들어 내부 Registry에 다음 형태로 mirror합니다.
registry.local/ai/pytorch:<approved-version>
registry.local/ai/nemo:<approved-version>
registry.local/ai/nccl-tests:<approved-version>
실제 POC에서는 버전을 고정해야 합니다.
예:
export CUDA_VERSION=13.3
export PYTORCH_VERSION=<approved>
export NEMO_VERSION=<approved>
export NCCL_VERSION=2.31.2
현재 NVIDIA가 제공하는 NCCL 2.31.2는 CUDA 13.3용이며 RHEL/CentOS 10용 local installer도 제공됩니다. (NVIDIA Developer)
중요: 실제 POC에서는 "latest"를 쓰지 말고 Driver/CUDA/NCCL/PyTorch/NeMo 버전을 하나의 BOM으로 freeze하는 것을 권장합니다.
Training 전에 B300 자체가 정상인지 확인합니다.
nvidia-smi
nvidia-smi -L
nvidia-smi topo -m
nvidia-smi nvlink -s
그리고 container에서:
docker run --rm --gpus all \
registry.local/ai/pytorch:<version> \
python -c "
import torch
print(torch.__version__)
print(torch.version.cuda)
print(torch.cuda.device_count())
for i in range(torch.cuda.device_count()):
print(i, torch.cuda.get_device_name(i))
"
Kubernetes라면:
kubectl run gpu-test \
--rm -it \
--restart=Never \
--image=registry.local/ai/pytorch:<version> \
--overrides='
{
"spec": {
"containers": [{
"name":"gpu-test",
"image":"registry.local/ai/pytorch:<version>",
"resources":{"limits":{"nvidia.com/gpu":1}},
"command":["python","-c","import torch; print(torch.cuda.get_device_name(0))"]
}]
}
}'
GPU count = expected
B300 device recognized
CUDA initialization = success
nvidia-smi = 정상
Xid error = 0
여기부터 실제 B300의 계산 성능을 측정합니다.
BF16
vs
FP8
Tensor Core 성능을 비교합니다.
PyTorch에서 matmul:
import torch
import time
device = "cuda"
N = 16384
a = torch.randn((N,N), device=device, dtype=torch.bfloat16)
b = torch.randn((N,N), device=device, dtype=torch.bfloat16)
for _ in range(20):
c = a @ b
torch.cuda.synchronize()
start = time.time()
for _ in range(100):
c = a @ b
torch.cuda.synchronize()
elapsed = time.time() - start
flops = 2 * N * N * N * 100
tflops = flops / elapsed / 1e12
print("BF16 TFLOPS:", tflops)
FP8은 Transformer Engine 기반으로 별도 측정합니다.
DCGM_FI_DEV_GPU_UTIL
DCGM_FI_DEV_GPU_MEM_USED
DCGM_FI_DEV_POWER_USAGE
DCGM_FI_DEV_SM_CLOCK
DCGM_FI_DEV_GPU_TEMP
가능하면 Tensor Core 관련 DCGM metric도 수집합니다.
실제 장비/동일 driver baseline 대비:
BF16 throughput >= baseline 90%
FP8 throughput >= baseline 90%
GPU utilization >= 95%
절대 TFLOPS 값을 PASS 기준으로 처음부터 고정하지 않는 것을 권장합니다.
B300 SKU/TDP/clock 설정에 따라 달라질 수 있기 때문입니다.
이 테스트가 B300 서버에서 매우 중요합니다.
GPU0
↕
NVSwitch
↕
GPU1~7
fabric이 정상인지 확인합니다.
nvidia-smi topo -m
nvidia-smi nvlink -s
추가로 NVIDIA가 NCCL 성능 troubleshooting에서 권장하는 nvbandwidth를 사용합니다. nvbandwidth는 GPU memory bandwidth 및 GPU-to-GPU bandwidth를 측정할 수 있습니다. (NVIDIA Docs)
예:
./nvbandwidth
GPU0 ↔ GPU1
GPU0 ↔ GPU2
GPU0 ↔ GPU7
all GPU
Expected NVLink topology
+
No NVLink error
+
All GPU pairs reachable
+
Measured bandwidth >= 90% of platform baseline
여기서 특정 GPU 하나만 bandwidth가 현저히 낮으면 training으로 넘어가면 안 됩니다.
이제 8 GPU를 하나의 distributed training system으로 봅니다.
NVIDIA의 nccl-tests는 NCCL operation의 performance와 correctness를 모두 검증하는 공식적인 테스트 도구입니다. (GitHub)
./build/all_reduce_perf \
-b 8M \
-e 8G \
-f 2 \
-g 8
그리고:
./build/all_gather_perf \
-b 8M \
-e 8G \
-f 2 \
-g 8
./build/reduce_scatter_perf \
-b 8M \
-e 8G \
-f 2 \
-g 8
NCCL test의 busbw를 핵심 지표로 사용합니다. NVIDIA 문서에서도 큰 message에서는 latency보다 bandwidth를 보는 것이 적합하다고 설명합니다. (GitHub)
처음에는 환경변수를 최소화하세요.
export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=INIT,GRAPH,NET
NVLink가 정상적으로 선택되는지 확인합니다.
Correctness = PASS
No NCCL error
8 GPU participate
busbw >= 90% baseline
그리고 반드시:
1 GPU
2 GPU
4 GPU
8 GPU
로 scaling을 측정합니다.
이제 진짜 Training입니다.
NVIDIA NeMo는 Llama 3.1에 대해 8B / 70B / 405B pretraining recipe를 제공합니다. 또한 8GPU/node 구성의 pretraining recipe 예제가 공식 문서에 있습니다. (NVIDIA Docs)
Llama 3.1 8B
첫 benchmark:
seq_length = 4096
처음부터 수 TB dataset을 쓰지 않습니다.
~10 GB
synthetic/pre-tokenized dataset
~100 GB
실제 representative dataset
1 × B300
2 × B300
4 × B300
8 × B300
모두 실행합니다.
이것이 중요합니다.
step_time
tokens/sec
samples/sec
GPU utilization
GPU memory
MFU
loss
NeMo recipe 개념상:
from nemo.collections import llm
pretrain = llm.llama31_8b.pretrain_recipe(
name="llama31_8b_b300",
dir="/workspace/checkpoints",
num_nodes=1,
num_gpus_per_node=8,
)
NeMo 공식 recipe는 실제 custom dataset으로 교체할 수 있도록 구성되어 있습니다. (NVIDIA Docs)
8GPU scaling efficiency:
2 GPU >= 1.7x
4 GPU >= 3.4x
8 GPU >= 6.5x
즉:
8GPU efficiency >= 81%
를 1차 목표로 잡겠습니다.
단, 이것은 NVIDIA의 공식 pass/fail 기준이 아니라 POC 운영 기준입니다.
여기부터 실제 AI workload에 가까워집니다.
Llama 3.1 70B
8 × B300
LoRA
BF16
FP8
두 조건을 비교합니다.
NVIDIA의 NeMo에는 Llama 70B fine-tuning recipe가 제공되며, full fine-tuning과 PEFT 방식 모두 지원합니다. (NVIDIA Docs)
POC용:
10~50 GB
정도면 충분합니다.
중요한 것은 dataset 크기가 아니라:
tokens processed
step time
tokens/sec
convergence
입니다.
seq_length = 4096
micro_batch = 1
global_batch = tuned
LoRA rank = 16 or 32
먼저 안정적으로 실행한 뒤 batch를 증가시킵니다.
No OOM
No NCCL error
GPU utilization > 90%
Stable loss
Checkpoint successful
성능:
>= 90% of baseline
이 테스트가 사용자 환경에서 가장 중요한 테스트 중 하나입니다.
구조:
B300 Node 1
8 GPU
│
│ NVLink
│
E810
│
│ RoCEv2
│
E810
│
B300 Node 2
8 GPU
GPU를 사용하지 않고:
ib_write_bw
ib_read_bw
를 실행합니다.
예:
# server
ib_write_bw -d <device> -R
# client
ib_write_bw <server-ip> -d <device> -R
측정:
Gbps
latency
retry
CNP
ECN
PFC
먼저:
export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=NET
NCCL log에서:
NET/IB
경로가 실제 선택되는지 확인합니다.
NCCL_SOCKET_IFNAME만 설정해서 해결하려고 하지 마세요.
RoCE에서는 NCCL/verbs/GID/interface 선택을 함께 봐야 합니다.
예를 들어 초기 진단에서:
export NCCL_IB_HCA=<E810_RDMA_DEVICE>
export NCCL_SOCKET_IFNAME=<bond1-interface>
정도를 사용하고, topology/selection이 확인되면 불필요한 환경변수는 제거합니다.
all_reduce_perf_mpi \
-b 8M \
-e 8G \
-f 2 \
-g 1
MPI launcher:
mpirun \
-np 16 \
-N 8 \
-H node01:8,node02:8 \
./build/all_reduce_perf_mpi \
-b 8M \
-e 8G \
-f 2 \
-g 1
nccl-tests는 MPI를 이용한 multi-node 실행을 지원하며, NVIDIA 예제도 node당 GPU 수를 지정하는 방식입니다. (GitHub)
16 GPU 참여
NCCL correctness PASS
NCCL NET/IB 사용
RDMA traffic 발생
우선순위:
1. Single-node NCCL baseline
2. Multi-node NCCL
3. Scaling efficiency
초기 POC 기준:
16GPU scaling efficiency >= 75%
를 PASS로 두겠습니다.
단, 현재 환경의 25GbE × 2 E810은 GPU 서버 간 training network로는 상당히 제한적일 수 있습니다.
즉 8×B300의 GPU compute에 비해:
25Gb × 2
는 매우 작은 network bandwidth입니다.
따라서 B300 자체 성능이 아니라 E810 2×25Gb network가 bottleneck이 될 가능성이 높습니다.
이 부분은 T7에서 반드시 숫자로 확인해야 합니다.
최종 테스트입니다.
구조:
AIStor
│
S3 / RDMA path
│
┌───────▼───────┐
│ Training Node │
│ │
│ DataLoader │
│ ↓ │
│ CPU memory │
│ ↓ │
│ B300 × 8 │
└───────────────┘
여기서는 training throughput뿐 아니라 storage가 GPU를 굶기지 않는지를 봅니다.
POC dataset:
100 GB
1차
1 TB
2차
정도로 구성합니다.
Object 크기는:
256 MB
512 MB
1 GB
정도로 합니다.
작은 object 수백만 개를 사용하면 training benchmark가 아니라 object-store benchmark가 되어버립니다.
초기:
num_workers = 8
prefetch_factor = 4
pin_memory = true
persistent_workers = true
그리고:
num_workers
8
16
32
64
를 sweep합니다.
반드시 세 가지를 비교합니다.
Local NVMe
→ GPU
AIStor
→ CPU
→ GPU
AIStor + optimized DataLoader
→ GPU
이렇게 해야 storage overhead를 분리할 수 있습니다.
GPU utilization
GPU memory
SM utilization
Tensor Core utilization
step_time
tokens/sec
samples/sec
MFU
loss
GET requests/sec
GET latency
throughput
5xx
connection errors
E810 RX/TX
RDMA bandwidth
PFC pause
ECN/CNP
packet drops
retransmission
CPU utilization
iowait
memory
NUMA locality
제가 실제 POC 보고서에서는 다음처럼 판정하겠습니다.
| Test | PASS |
|---|---|
| T1 | GPU/CUDA 정상, Xid=0 |
| T2 | BF16/FP8 ≥90% baseline |
| T3 | NVLink/NVSwitch 정상, ≥90% baseline |
| T4 | NCCL correctness + ≥90% baseline |
| T5 | 8GPU scaling ≥81% |
| T6 | 70B LoRA 정상 + stable loss |
| T7 | 16GPU NCCL/RDMA + scaling ≥75% |
| T8 | AIStor 사용 시 training throughput ≥90% local-storage baseline |
단, T2~T8의 % 기준은 NVIDIA 공식 certification 기준이 아니라 이번 POC의 engineering gate로 사용하는 것이 적절합니다.
사용자 환경에서는 이미 Prometheus/Grafana를 사용하고 있으므로 별도 monitoring stack을 만들 필요가 없습니다.
GPU Utilization
GPU Memory
Power
Temperature
SM Clock
Tensor Core
PCIe TX/RX
NVLink TX/RX
XID
DCGM Exporter를 사용합니다.
Training process log에서:
step_time
tokens/sec
NCCL time
compute time
communication time
을 추출합니다.
핵심은:
communication_time / step_time
입니다.
예를 들어:
Step = 1.0 sec
Compute 0.65 sec
NCCL 0.30 sec
Data loading 0.05 sec
이면 상당히 좋은 상태입니다.
반대로:
Compute 0.50
NCCL 0.45
Data loading 0.05
이면 multi-node scaling의 병목이 NCCL입니다.
E810에서는 특히:
RDMA TX
RDMA RX
QP count
CNP
ECN
PFC pause
packet drop
retry
를 봅니다.
사용자 환경에서는 bond1이 기존 Kubernetes internal traffic과 공유되므로 이 부분이 아주 중요합니다.
Training 중:
AIStor
+
Cilium
+
K8s
+
NCCL
이 동시에 bond1을 사용하면 network contention이 발생할 수 있습니다.
GET/s
GET latency
bytes/s
5xx
connection errors
active connections
를 수집합니다.
특히 training에서:
GPU utilization ↓
AIStor GET latency ↑
가 동시에 발생하면 GPU 문제가 아니라 data pipeline 문제일 가능성이 높습니다.
현재 사용자의 Intel Xeon 환경에서는 T8에 다음 테스트를 추가하는 것을 강하게 추천합니다.
NUMA 0 CPU
│
├── NIC
│
└── GPU group
NUMA 1 CPU
│
├── NIC
│
└── GPU group
그리고 비교:
NUMA-aware DataLoader
vs
NUMA-unaware DataLoader
입니다.
측정:
tokens/sec
CPU memory bandwidth
GPU utilization
PCIe traffic
RDMA bandwidth
step time
이 차이가 상당히 클 수 있습니다.
T1 GPU sanity
└─ nvidia-smi
└─ CUDA
└─ container
└─ PASS/FAIL
T2 Compute
└─ BF16
└─ FP8
└─ Tensor Core
└─ TFLOPS
T3 NVLink
└─ nvidia-smi topo
└─ nvbandwidth
└─ GPU↔GPU
T4 NCCL
└─ all_reduce
└─ all_gather
└─ reduce_scatter
└─ 1/2/4/8 GPU
T5 Llama 3.1 8B
└─ BF16
└─ 1/2/4/8 GPU
└─ scaling
T6 Llama 3.1 70B
└─ LoRA
└─ BF16
└─ FP8
└─ convergence
T7 Multi-node
└─ 2 × B300 node
└─ NCCL
└─ E810
└─ RoCE
└─ 16 GPU scaling
T8 E2E
└─ AIStor
└─ DataLoader
└─ NUMA
└─ RDMA
└─ NCCL
└─ LLM training
이렇게 하면 "B300이 동작한다" 수준의 POC가 아니라, 실제 운영 환경에서 B300을 Kubernetes에 넣었을 때 학습 성능이 어디에서 제한되는지까지 확인할 수 있습니다.
특히 사용자의 환경에서는 T7/T8이 가장 중요합니다. 8×B300 자체의 GPU 성능보다도 B300 ↔ NVSwitch ↔ NCCL ↔ E810/RoCE ↔ AIStor 경로가 실제 training throughput을 결정할 가능성이 높기 때문입니다. NCCL 자체도 topology-aware collective communication을 제공하고, multi-GPU/multi-node training의 핵심 통신 계층으로 사용됩니다. (NVIDIA Docs)
한 가지 중요한 현실적인 조정: 처음 T5~T8을 실행할 때는 최신 Llama/NeMo/FP8 조합을 바로 고정하지 말고, B300에서 검증된 NVIDIA NGC PyTorch/NeMo 컨테이너 + 현재 승인된 Driver/CUDA/NCCL 조합을 먼저 freeze하는 것이 좋습니다. 그래야 성능 문제가 GPU/네트워크 문제인지 framework compatibility 문제인지 분리할 수 있습니다.