Running MiniMax H3 Ref2VA on 2x RTX 5090 under a 116 GB cgroup — streaming weight load + resident-layer GPU routing (4 patches, SGLang 0.5.17) #34426
Replies: 2 comments
|
Hi OP, I have two Sparks (essentially a 5060 with 128GB VRAM) connected using a 200Gbps Connect-X7 network cable. This works great for LLMs, a patched VLLM distributed across two sparks accelerates tok/sec generation. I've been running H3 on one. The model fits entirely in VRAM so this isn't the same challenge as two 5090s. It's the slow gen times due to weak compute. I saw that sglang seems to support running H3 across two cards, so I was wondering if this type of parallelism accelerates compute if two GPUs are available, when the model already full fits in the RAM of one "GPU". Do you know if it's worth spending the week-end learning to use sglang? |
|
Hey, building Throttle: semantic cache for self-hosted inference. Cuts repeat-query costs 40-60%, zero code changes. Works with vLLM, Ollama, SGLang, LMDeploy. Open-source, free beta. Looking for users to test: |
Uh oh!
There was an error while loading. Please reload this page.
I got MiniMax H3 Ref2VA (33B DiT + Qwen3VL, full BF16, ~123 GB) to load and run on 2× RTX 5090 under a host cgroup
memory.max=116 GBthat could not be raised. Load + inference both verified (1344×768 / 4.5 s video out, peak GPU 18.7 GB, peak CPU 114.7 GB).Why it OOMs by default: SGLang's
hf_to_custom_state_dictmaterializes the entire converted DiT weight dict on CPU at once (~61.7 GB), on top of the ~58 GB resident Qwen3VL text encoder. That sum exceeds 116 GB and the load dies at shard 13/13 every time. TP=2 does not help because both ranks share the same cgroup.The fix is 4 source patches to
sglang/multimodal_gen/(SGLang 0.5.17):utils.py): newstream_hf_to_custom_state_dictgenerator that yields one converted tensor at a time — the 61.7 GB dict is never built.fsdp_load.py): load loop consumes the generator +del full_tensoreach iteration; FP8 dequant gets a shim (unsupported during streaming, BF16 never hits it).transformer_loader.py+fsdp_load.py): threadresident_layers/resident_layer_attrfromserver_argsdown to the loader (the layerwise manager is only configured after loading, somodel.layerwise_offload_managersis empty at load time).fsdp_load.py): resident-layer params (regex^blocks\.(\d+),layer_idx < resident_layers) skipcpu_offloadand land directly on GPU.Gotchas worth flagging:
--pin-cpu-memory falseis mandatory — pin_memory allocates ~53 GB of unreleasable shmem that alone exceeds the ceiling.model_cls.layer_namesis an instance attr (set in__init__, not at load-planning time); fall back tomodel.layer_names, then hardcode"blocks".ninja-build(JIT kernels) andffmpeg(ffprobepost-processing) system-wide.Full patches, the
sglang servecommand, the inference call shape, and the memory-curve numbers are in the gist:https://gist.github.com/ft54482/b5489349620c7f0fa63e634e3356d79b
Sharing in case anyone else is fighting the same cgroup-OOM during SGLang DiT loading. Happy to turn the streaming loader into a PR if the maintainers are interested — it's a pure memory win with no behavior change for non-cgroup-limited hosts.
All reactions