Skip to content

vLLM tensor parallelism fails in a container because shared memory is limited to 64 MB

A container gets 64 MB of shared memory by default. PyTorch and NCCL use that space to move data between the worker processes of a tensor-parallel deployment, so a model that runs on one GPU fails to initialise across several, with an error naming shared memory rather than the model.

Quick answer

Run df -h /dev/shm inside the container. If it reads 64 MB, raise the shared memory size or use host IPC; on Kubernetes mount an emptyDir with the memory medium at /dev/shm.

Infrastructure#vllm#tensor-parallel#shared-memory#docker#nccl#kubernetes

What this failure is

A container configuration failure in which the default 64 MB shared memory mount is too small for the inter-process transfers that tensor-parallel vLLM and NCCL perform, preventing the engine from initialising across multiple GPUs.

Why it happens (the mechanism)

The shared memory default is a property of the container runtime, chosen without reference to collective communication. vLLM's workers exchange tensors through that mount and NCCL creates segments in it during setup, so a limit that is generous for a web service is far too small here. Because a single-GPU deployment never touches the segment, the constraint stays hidden until the day someone scales across devices.

What you'll observe

  • The same image and model work with one GPU and fail with two or more
  • The failure occurs during initialisation, before any request is served
  • The error names NCCL or a shared memory segment, which does not obviously implicate the container runtime
  • The deployment works locally and fails on the orchestrator, or the reverse

Common symptoms and what they mean

SymptomWhy it happens
torch.distributed.DistBackendError: NCCL error, unhandled system error, ncclSystemErrorContainer runtimes mount a small tmpfs at /dev/shm by default, historically 64 MB. That default was chosen for ordinary applications and is unrelated to what collective communication libraries need.
NCCL WARN Error while creating shared memory segment /dev/shm/nccl-vzIpS6Tensor-parallel vLLM moves tensors between worker processes through that space, and NCCL creates segments there during communicator setup. When the mount is too small the segment cannot be created and initialisation fails with a system error that names the segment rather than the limit, which is why the cause is not obvious from the message.
A warning that the object store is using /tmp instead of /dev/shm because /dev/shm has only 67108864 bytes available, which will harm performanceThe failure is invisible on a single GPU because nothing needs the shared segment. It appears the first time the deployment is scaled across devices, which is often long after the image was validated.
Initialisation hanging at ncclCommInitRank with no further outputContainer runtimes mount a small tmpfs at /dev/shm by default, historically 64 MB. That default was chosen for ordinary applications and is unrelated to what collective communication libraries need.

Which systems are affected

  • Docker containers started without --shm-size or --ipc=host, which receive the 64 MB default
  • Kubernetes pods, where the default shared memory size is frequently too small for these containers
  • Docker Swarm, which does not support the host IPC option at all
  • Any tensor-parallel or pipeline-parallel vLLM deployment, since single-GPU serving does not exercise this path

How to confirm this is the problem

Apply the following checklist to a small reproduction: each box below is a positive signal that you are looking at this exact failure rather than a sibling in the same taxonomy.

  • Run df -h /dev/shm inside the container. A total of 64 MB confirms the default mount is in place and is the limit being hit.
  • Start the identical image with tensor parallel size 1. Success on one GPU and failure on more localises the problem to inter-worker communication rather than to the model or weights.
  • Re-run with NCCL_DEBUG=INFO and read the first warning. A message naming a shared memory segment points here; one naming peer access points at the transport instead.

Example training logs (fingerprint)

training.log (synthetic fingerprint)
NCCL WARN Error while creating shared memory segment /dev/shm/nccl-vzIpS6 (size 9637888)
torch.distributed.DistBackendError: NCCL error: unhandled system error (run with NCCL_DEBUG=INFO for details)
WARNING: /dev/shm has only 67108864 bytes available. This will harm performance! You may be able to free up space by deleting files in /dev/shm.

Timestamps and exact values vary across runs, but the pattern. An info-level start, an early WARN, an ERROR carrying the symptom. Is the actual fingerprint you should alert on. The Denpex platform flags this combination automatically.

Root cause, fix & prevention, signed in

Sign up free to see why this failure really happens, the exact remediation steps, and the production-grade prevention pattern. You also get 3 free full diagnoses for your own training logs.

Sign up free. Unlock the full analysis

No credit card · 3 free diagnoses · Instant access

Why the recommended fix works

Enlarging the mount, or sharing the host's, gives the segment room to be created, so communicator setup completes and the workers can exchange tensors. It is a configuration change to the container rather than to vLLM, which is why no vLLM flag resolves it and why the same image behaves differently across environments.

Code examples

typical reference pattern
// Typical pattern:
import torch.optim as optim
optimizer = optim.AdamW(model.parameters(), lr=3e-4)
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=num_training_steps)
for step in range(num_training_steps):
    optimizer.zero_grad()
    loss = model(batch)
    loss.backward()
    optimizer.step()
    scheduler.step()

Adapt the snippet to your framework. The same pattern holds for PyTorch Lightning, Hugging Face Trainer, DeepSpeed, Megatron-LM, and vLLM training wrappers. Where the wrapper exposes a config flag (for examplelr_scheduler_type in Trainer), prefer the flag over the imperative API to keep the schedule declarative and reproducible.

Best practices by model family

Model / StackRecommendationNotes
Docker, single host--shm-size=16g or --ipc=hostEither gives the segment room; host IPC shares the host's mount directly.
KubernetesemptyDir with medium Memory and a sizeLimit at /dev/shmThe pod default is generally too small for these containers.
Docker SwarmShared memory size setting onlySwarm does not support the host IPC option.
GPUDirect RDMA in useAdd the IPC_LOCK capabilityNamed in vLLM's troubleshooting guide as a cause of communicator initialisation failure.

With the fix vs without the fix

DimensionWith the fixWithout the fix
Where the limit comes fromThe container runtime's default mountAssumed to be a vLLM or model setting
When it becomes visibleThe first multi-GPU startExpected during single-GPU validation
A large and free mountStill fails if segments are being cleaned up underneathTaken as proof shared memory is not the problem

Real engineering notes

A large shared memory mount does not always end the investigation. One reported case had 252 GB provisioned through host IPC and verified more than 98 percent free, and still failed during communicator setup when late-joining ranks tried to attach to segments, reporting no such file or directory at size zero. The suspect there was segment cleanup rather than capacity, addressed by stopping systemd from removing IPC segments still in use. Check the size first because it is nearly always the cause, but do not conclude the mount is innocent merely because it is large.

Visual fingerprint

Why one GPU works and two do not
  tensor parallel size 1     worker0 -> GPU0                 /dev/shm unused
  tensor parallel size 2     worker0 <-> worker1             /dev/shm REQUIRED
                                    via /dev/shm segments
                             default mount = 64 MB  ->  segment creation fails
A single worker never uses the shared memory mount, so the 64 MB default goes unnoticed. Two or more workers exchange tensors and create NCCL segments there, and the segment creation fails against the default limit.

Root cause, fix & prevention

Frequently asked questions

Twelve targeted questions that engineers and on-call staff most commonly ask about this failure.

Why does it work on one GPU?
A single worker has nothing to exchange, so the shared memory mount is never used. The limit only binds once two or more workers must pass tensors between themselves.
Is this a vLLM bug?
No. It is a container runtime default. No vLLM flag changes it, which is why the same image succeeds or fails depending on how it was started.
I already use --ipc=host and it still fails.
Check whether IPC segments are being removed while still in use. One reported case had 252 GB free and still failed at communicator setup; preventing systemd from deleting active segments resolved it.
What is the right size?
Provision generously rather than minimally, for example 16 GB, and set it in the compose file or pod spec so it does not depend on a runtime default that differs between environments.

Don't just read the fix, diagnose your run

The encyclopedia tells you what went wrong. Denpex tells you what went wrong in YOUR training run. With your logs, your config, and your stack.