Skip to content

Commit 430e6e7

Browse files
committed
[perf]: Load H3 DiT weights onto CUDA, not CPU
GB10 unified memory made the CPU-then-copy path take minutes for the 35B FastH3 transformer. When host offload is off, read safetensors onto the accelerator.
1 parent 9a7a796 commit 430e6e7

3 files changed

Lines changed: 13 additions & 7 deletions

File tree

docs/getting_started/installation/spark_performance.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ is power-cycled. To avoid it:
165165
conditioner is tens of gigabytes of BF16. If the DiT and VAEs load while that
166166
encoder is still resident, the process is a typical `earlyoom` kill (Python is
167167
preferred). The CUDA pipeline now encodes first, releases the encoder, then
168-
loads DiT and VAEs. See [Offloading](../../inference/offloading.md).
168+
loads DiT and VAEs onto the accelerator (`to_cpu` follows `cpu_offload`, which
169+
is off here). See [Offloading](../../inference/offloading.md).
169170

170171
## Gotchas specific to the GB10
171172

docs/inference/offloading.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ disable FSDP. `pin_cpu_memory` is not an offload mode and is left unchanged.
2424
MiniMax H3 CUDA inference uses a second lever that does not copy weights to a
2525
host pool. The pipeline loads the Qwen3-VL text encoder, runs conditioning, then
2626
releases that encoder before it loads the DiT and video/audio VAEs. The MLX FastH3
27-
runtime uses the same phase order. Input-preparation geometry (spatial ratio,
28-
latent channels, audio sample rate) comes from the VAE arch configs until those
29-
weights load. A later `generate()` on the same worker currently re-enters
30-
conditioning after the encoder has been released; start a new generator for a
31-
new prompt until prompt-cache reload exists.
27+
runtime uses the same phase order. When host offload is off, DiT safetensors are
28+
read onto the accelerator instead of CPU-then-copy. Input-preparation geometry
29+
(spatial ratio, latent channels, audio sample rate) comes from the VAE arch
30+
configs until those weights load. A later `generate()` on the same worker
31+
currently re-enters conditioning after the encoder has been released; start a
32+
new generator for a new prompt until prompt-cache reload exists.
3233

3334
## Behavior Explanation
3435

fastvideo/models/loader/fsdp_load.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,11 @@ def maybe_load_fsdp_model(
239239
fsdp_shard_conditions=model._fsdp_shard_conditions,
240240
pin_cpu_memory=pin_cpu_memory)
241241

242-
weight_iterator = safetensors_weights_iterator(weight_dir_list, to_cpu=True)
242+
# Host offload is already disabled on unified memory (GB10). Staging the
243+
# 35B FastH3 DiT on CPU and then copying to CUDA doubled that working set
244+
# and took minutes. Follow cpu_offload: read onto the accelerator.
245+
weight_iterator = safetensors_weights_iterator(weight_dir_list, to_cpu=cpu_offload)
246+
logger.info("Loading transformer weights with to_cpu=%s", cpu_offload)
243247
param_names_mapping_fn = get_param_names_mapping(model.param_names_mapping)
244248
dense_lora_patch = DenseLoRAPatch.from_adapter(
245249
lora_path,

0 commit comments

Comments
 (0)