Large models: several cards, several nodes#
A model too big for one card runs on several. llmgw chooses how from the model's own figures and the cluster as it is; this page is the rules it follows, the commands, and what to look at when a first one is brought up on new hardware.
How a model is split#
In order, the first that fits:
- One card. Nothing to split.
- Several cards of one node, tensor parallel. Every layer is cut
across the cards, so they talk for every token: they must be on one
NVLink domain. The agent reads
nvidia-smi topo -mand gives a replica the cards with the most NVLink between them (install.md). - Several nodes, pipeline parallel between them. Each node holds a run of layers on all its cards (tensor parallel inside it), and only a layer's output crosses to the next node. The nodes must share one InfiniBand or RoCE fabric: a replica never spans two, and never a node with none. Any number of nodes, not only two or four.
The plan takes the fewest cards, then the fewest nodes, then the better precision up to eight bits.
Tensor width and the KV heads. The cards split the model's KV heads among them, or past their number each card holds a copy of one. So the width divides the KV heads or is a multiple of them: a model with 8 KV heads runs 2, 4, 8 or 16 wide, not 12. Qwen3-235B has 4 and runs on 8.
Mixture of experts. A model of experts (Qwen3-235B-A22B, DeepSeek-V3,
Llama 4, Mixtral) on more than one card is served with vLLM's
--enable-expert-parallel: each card holds whole experts rather than a
slice of every one, which is less traffic per token. It is read from
config.json (num_experts, n_routed_experts, num_local_experts).
When it does not fit. A smaller precision first: an FP8 or AWQ
repository of the same model, or a GGUF quantisation on llama.cpp if one
node's cards hold it. Then more nodes. llmgw ctl model plan REPO --precision bf16,fp8 shows each precision's fit from the model's config.
What a way needs#
Each way the plan offers says what a replica needs of each card, part by part, and of all its cards together:
$ llmgw ctl model plan meta-llama/Llama-3.3-70B-Instruct --format safetensors --context 32768
FILE SIZE BEST WAY A CARD OF ALL CARDS NOW
original 131 GB 4 × h100-80g 37.4 GB 72 GB 150 GB free
Best: original on 4 × h100-80g: 37.4 GB a card (weights 32.9 + context 2.5 + engine 2.0) of 72 usable; 150 GB on 4 cards.
The context costs 0.31 GB per 1000 tokens, the whole model (--context to plan another).
- weights: the files, divided over the cards.
- context: the KV cache for the context planned, divided likewise.
- engine: the engine's own: 2 GB and a fiftieth of the weights for vLLM.
- usable: 90% of a card; the rest is the driver's and fragmentation's.
The console's Serve a model shows the same for every way a file runs. A context longer than planned is checked against it before anything is fetched.
Serving one#
Without flags the plan's best way is taken:
llmgw ctl model serve Qwen/Qwen3-235B-A22B-Instruct-2507-FP8 --format safetensors --context-length 32768
Or a way given by hand, for instance two nodes of eight:
llmgw ctl model serve meta-llama/Llama-3.3-70B-Instruct --format safetensors \
--gpu-class h100-80g --gpus 8 --nodes 2 --env NCCL_DEBUG=INFO
--gpus is the cards on each node and --nodes the nodes. The pipeline
is the nodes and the tensor width the cards of each.
--env KEY=VALUE goes into the engine's environment on every node:
NCCL_DEBUG=INFO while bringing a cluster up, NCCL_IB_* to steer it.
Only the variables engines are tuned with are taken. llmgw already sets
these:
NCCL_IB_HCAto the fabric's adapters;NCCL_IB_GID_INDEXon RoCE;NCCL_SOCKET_IFNAMEto the management network;- for an NVLink domain spanning nodes,
NCCL_MNNVL_ENABLE.
The job's first step says what it needs of each card. The weights then
come to the mirror once and from it to each node. The startup timeout (20
minutes unless the profile's startup_timeout says otherwise) runs from
when a node's download last moved. So a model of hundreds of gigabytes is
not failed while it is still arriving, and one whose download stops is
failed that long after.
Watching it come up#
| What | Where |
|---|---|
| The replica and its shards, one per node, each with its download | llmgw ctl replicas |
| Why it is not placed | llmgw ctl explain-placement MODEL |
A node's engine output (NCCL's lines with NCCL_DEBUG=INFO) |
llmgw ctl logs NODE --source SHARD |
| The bandwidth between two nodes, rail by rail | llmgw ctl fabric-test NODE NODE |
| Each node's GPUs, NVLink and adapters | llmgw doctor on the node; its page under /admin |
| Every step of a start, across nodes | the replica start trace (install.md) |
With NCCL_DEBUG=INFO, NCCL says which transport it took between nodes:
NET/IB is the fabric. NET/Socket means it fell back to TCP, and the
model will run, slowly.
Bringing it up on new hardware#
A first run on a fabric, in order. Each step is worth its output if something goes wrong.
- The nodes. Add each with its fabric:
llmgw node add host --fabric ib-a:mlx5_0,mlx5_1. Thenllmgw ctl nodesshows every node ready, onib-a. - The fabric.
llmgw ctl fabric-test node1 node2: each rail at its rated speed (a 400 Gb/s rail near 45 GB/s). - One node, several cards. A dense 70B at bf16 on four or eight
cards of one node, by the plan:
llmgw ctl model serve meta-llama/Llama-3.3-70B-Instruct --format safetensors. Ready, then a question answered. - Two nodes. The same model forced over two:
--gpu-class CLASS --gpus 8 --nodes 2 --env NCCL_DEBUG=INFO, under another--name. Ready, answering, andNET/IBin both shards' logs. - Experts. A mixture-of-experts model on one node's eight cards,
for instance
Qwen/Qwen3-235B-A22B-Instruct-2507-FP8: its profile carries--enable-expert-parallel(llmgw ctl models, or its definition from the admin API). - A node lost. With the two-node replica serving, stop one node's
agent (
systemctl stop llmgw-agent): the replica fails and is placed again once the node is back or another has room. Nothing is left holding cards.
For each, worth keeping:
- the time from serve to ready;
- tokens a second from
llmgw ctl bench; - the plan's per-card figure against what
nvidia-smishows once loaded; - anything it said that was wrong.