soobook
GPU

NVLink and NVSwitch

PCIe와 NVLink의 차이, NVSwitch가 필요한 이유, GPU끼리 빠르게 통신하는 경로

NVLink는 GPU끼리 데이터를 주고받는 고대역폭 interconnect다. NVSwitch는 여러 GPU의 NVLink를 switch fabric으로 묶어, GPU pair마다 직접 링크가 없어도 넓고 예측 가능한 경로로 통신하게 만든다.

GPU 한 장만 쓸 때는 주로 CPU와 GPU 사이를 본다. CPU RAM의 데이터를 GPU memory로 옮기고, kernel이 HBM에 있는 tensor를 읽고 쓰는 흐름이 중심이다.

GPU가 여러 장이면 CPU를 거치는지, GPU끼리 바로 오가는지가 성능에 더 큰 영향을 준다. GPU 0에 있는 activation이나 gradient를 GPU 1이 읽어야 한다면, 그 데이터가 어떤 경로로 이동하는지 봐야 한다.

{
  "diagram": "html-diagram",
  "variant": "explainer",
  "title": "NVLink / NVSwitch",
  "width": 960,
  "height": 460,
  "mobileWidth": 820,
  "regions": [
    {
      "id": "nvlink-fabric",
      "label": "NVLink fabric",
      "x": 52,
      "y": 58,
      "width": 856,
      "height": 340
    }
  ],
  "nodes": [
    {
      "id": "nvswitch",
      "kind": "switch",
      "label": "NVSwitch",
      "caption": "switch fabric",
      "x": 480,
      "y": 160,
      "width": 176,
      "height": 68
    },
    {
      "id": "nv-gpu-0",
      "kind": "gpu",
      "label": "GPU 0\\nHBM",
      "caption": "source",
      "x": 220,
      "y": 326,
      "width": 126,
      "height": 70
    },
    {
      "id": "nv-gpu-1",
      "kind": "gpu",
      "label": "GPU 1\\nHBM",
      "caption": "target",
      "x": 480,
      "y": 326,
      "width": 126,
      "height": 70
    },
    {
      "id": "nv-gpu-n",
      "kind": "gpu",
      "label": "GPU N\\nHBM",
      "caption": "target",
      "x": 740,
      "y": 326,
      "width": 126,
      "height": 70
    }
  ],
  "links": [
    {
      "id": "gpu0-to-switch",
      "path": "M 220 291 C 260 230 336 188 392 164",
      "tone": "primary",
      "width": 3,
      "flow": {
        "speed": "normal",
        "count": 2,
        "emphasis": "strong"
      }
    },
    {
      "id": "switch-to-gpu1",
      "points": [[480, 194], [480, 291]],
      "tone": "primary",
      "width": 3,
      "flow": {
        "speed": "normal",
        "count": 2,
        "emphasis": "strong"
      }
    },
    {
      "id": "switch-to-gpun",
      "path": "M 568 164 C 624 188 700 230 740 291",
      "tone": "primary",
      "width": 3,
      "flow": {
        "speed": "normal",
        "count": 2,
        "emphasis": "strong"
      }
    }
  ],
  "labels": [
    {
      "text": "NVLink",
      "x": 318,
      "y": 220
    },
    {
      "text": "NVLink",
      "x": 642,
      "y": 220
    }
  ]
}

PCIe

PCIe는 GPU만을 위한 전용 연결이 아니다. CPU, NIC, NVMe SSD, GPU 같은 장치를 host system에 붙이는 범용 I/O interconnect다.

일반적인 서버에서 GPU는 PCIe root complex나 PCIe switch 아래에 붙는다. CPU가 GPU memory로 데이터를 복사하거나, GPU kernel launch를 제출하거나, device 상태를 읽을 때 이 경계를 지난다.

GPU끼리도 PCIe peer-to-peer access를 쓸 수 있는 경우가 있다. 하지만 이 경로는 topology 영향을 크게 받는다. 두 GPU가 같은 PCIe switch 아래에 있는지, 다른 CPU socket 아래에 있는지, ACS나 IOMMU 설정이 어떤지에 따라 경로와 성능이 달라진다.

이 구조에서는 GPU 0과 GPU 1이 같은 서버 안에 있어도 GPU-to-GPU 전용 경로가 항상 넓다고 보기는 어렵다. PCIe는 범용 연결이고, GPU끼리의 대량 통신만을 위해 설계된 fabric은 아니다.

NVLink는 NVIDIA GPU 사이를 연결하는 고대역폭, 저지연 interconnect다. CPU와 주변 장치를 묶는 PCIe와 달리, NVLink는 GPU memory 사이의 traffic을 빠르게 보내는 데 초점이 있다.

Multi-GPU workload에서는 GPU들이 서로 데이터를 주고받는다.

  • Data parallel training은 gradient를 모은다.
  • Tensor parallel inference는 layer 계산 중간 결과를 GPU 사이에 나눠 읽는다.
  • Pipeline parallelism은 stage 사이 activation을 옮긴다.
  • MoE 모델은 token routing과 expert output을 GPU 사이에서 주고받는다.

이때 GPU 0의 HBM에 있는 데이터를 GPU 1이 자주 읽어야 한다면 PCIe만으로는 부족해질 수 있다. NVLink는 이 GPU-to-GPU traffic을 더 직접적으로 처리하기 위해 등장한다.

NVLink가 GPU memory를 하나로 합치는 것은 아니다. 각 GPU의 HBM은 여전히 각 GPU에 붙어 있다. 대신 GPU가 다른 GPU의 memory에 접근하거나, NCCL 같은 library가 collective communication을 수행할 때 더 빠른 경로를 쓸 수 있다.

NVSwitch

GPU가 두 장이나 네 장일 때는 GPU pair를 직접 연결하는 구조를 생각할 수 있다. 하지만 GPU 수가 늘어나면 모든 pair를 충분히 넓게 직접 연결하기 어렵다. 필요한 링크 수가 빠르게 늘어나기 때문이다.

NVSwitch는 이 문제를 switch fabric으로 푼다. 각 GPU의 NVLink가 NVSwitch에 연결되고, NVSwitch가 GPU 사이 traffic을 중계한다.

이 구조에서는 GPU pair가 특정 직접 링크에만 의존하지 않아도 된다. GPU가 많아질수록 “몇 번 GPU와 몇 번 GPU가 직접 연결되어 있는가”보다 “fabric 전체가 어떤 bandwidth와 routing을 제공하는가”가 더 중요해진다.

NVIDIA의 NVSwitch 기반 시스템에서는 Fabric Manager 같은 소프트웨어도 중요하다. Hardware switch만 있으면 끝나는 것이 아니라, GPU driver와 함께 NVLink와 NVSwitch fabric을 초기화하고 관리해야 한다.

Why NVSwitch

NVSwitch가 필요한 상황은 all-to-all communication에서 잘 드러난다.

예를 들어 8개 GPU가 있고, 각 GPU가 다른 모든 GPU와 gradient shard를 주고받아야 한다고 하자. 어떤 pair는 직접 빠른 링크를 타고, 어떤 pair는 돌아가야 한다면 collective 성능이 topology에 크게 흔들린다.

NVSwitch fabric은 이런 차이를 줄인다. GPU 사이의 통신을 switch fabric 안으로 모아, 더 균일한 경로를 제공한다. 그래서 all-reduce, all-gather, reduce-scatter 같은 collective operation의 병목을 줄이는 데 중요하다.

LLM inference에서도 비슷하다. 큰 모델을 여러 GPU에 나누면 한 token을 만들 때도 GPU 사이 통신이 반복된다. Compute가 충분히 빨라도 중간 activation이나 expert output을 주고받는 경로가 좁으면 latency가 튄다.

요즘 NVIDIA 자료에서는 NVLink domain이라는 표현이 자주 나온다. NVLink와 NVSwitch fabric으로 서로 연결된 GPU 묶음을 가리키는 말로 보면 된다.

예를 들어 DGX B200은 8개의 B200 GPU와 5세대 NVLink switch를 사용한다. NVIDIA의 NVL72 계열 자료는 Blackwell GPU 72개를 하나의 rack-scale NVLink domain으로 묶는 구조를 설명한다. 여기서 NVLink는 단순한 짧은 케이블이 아니라, GPU rack 안의 compute fabric에 가깝다.

다만 “하나의 거대한 GPU처럼 보인다”는 표현은 성능과 programming model을 설명하기 위한 비유다. 물리적으로는 여러 GPU, 여러 HBM, 여러 switch가 있고, 소프트웨어 stack이 그 위에서 통신을 최적화한다.

NCCL

NCCL은 NVIDIA Collective Communications Library의 약자다. 여러 GPU가 데이터를 주고받을 때 쓰는 communication library이며, all-reduce, all-gather, reduce-scatter, broadcast 같은 collective operation을 구현한다.

Collective operation은 GPU 하나가 다른 GPU 하나로만 데이터를 보내는 함수가 아니다. 여러 GPU가 같은 통신 연산에 참여해 gradient, activation, shard를 교환하는 패턴에 가깝다. PyTorch DDP, FSDP, tensor parallel runtime은 이런 통신을 직접 구현하기보다 NCCL을 통해 처리하는 경우가 많다.

애플리케이션 코드가 NVSwitch packet을 직접 다루는 경우는 드물다. 보통은 PyTorch, CUDA library, NCCL 같은 계층을 통해 간접적으로 사용한다.

개발자가 호출하는 API는 collective operation 하나일 수 있다. 아래에서는 NCCL이 GPU topology를 보고 algorithm과 channel을 고른다. NVLink와 NVSwitch가 있으면 NCCL은 그 경로를 활용해 GPU끼리 데이터를 주고받을 수 있다.

NVLink/NVSwitch를 볼 때는 다음을 확인하면 된다.

  • 왜 같은 GPU 개수인데 서버마다 multi-GPU 성능이 다른가
  • nvidia-smi topo -m을 확인해야 하는가
  • 왜 training에서 all-reduce 시간이 병목이 되는가
  • 왜 rack-scale GPU system에서 switch가 GPU만큼 중요해지는가

Summary

PCIe는 CPU 중심의 범용 I/O 경로다. GPU를 host system에 붙이고, CPU와 GPU 사이의 제어와 데이터 이동을 처리한다.

NVLink는 GPU-to-GPU 통신을 위한 고대역폭 경로다. GPU memory 사이의 read/write와 collective traffic에서 중요해진다.

NVSwitch는 여러 GPU의 NVLink를 switch fabric으로 묶는다. GPU 수가 늘어날 때 pair별 직접 연결의 한계를 줄이고, 더 균일한 GPU-to-GPU communication을 제공한다.

Multi-GPU 성능은 GPU 개수만으로 결정되지 않는다. GPU들이 어떤 fabric으로 연결되어 있는지, 그 fabric을 NCCL과 driver가 어떻게 쓰는지까지 함께 봐야 한다.

References