~/blog/h3-ltx-two-stage-dgx-spark

DGX Spark · part 47

[Video] MiniMax H3 Super Acceleration on a DGX Spark: 2x native cold, 3.14x warm

❯ cat --toc

TL;DR

On a DGX Spark, MiniMax-H3 drafting at 672x384 and LTX-2.5 refining to 1344x768 takes 118.8 s cold, against 237.7 s for native H3 at full size: 2.00x. Run both again with the models still loaded and the gap opens to 73.3 s against 230.1 s, or 3.14x. The Spark's 121 GiB of unified memory holds both stages' 53.6 GiB of weights at once, so nothing gets evicted between runs. A 31.84 GiB RTX 5090 cannot hold stage 1's 33.5 GiB alone and reloads every time. Caveat: in absolute terms the Spark is 2.4-5.5x slower than a 5090 here, 118.8 s against 40.3 s. This pipeline needs ComfyUI 0.34.0 or newer — below that the refine quietly produces garbage frames.

🔊 Sound on. A 672x384 four-step draft, refined to 1344x768 in three LTX-2.5 steps, audio from H3 throughout. This is the artifact behind the 73.3 s warm cell — every second in this article was measured on this prompt and this seed.

Hand-drawn social cover: an anthropomorphised DGX Spark box comfortably holds two blocks labelled H3 and LTX-2.5, while a smaller RTX 5090 beside it strains to hold only H3 and has dropped LTX-2.5 at its feet. Four info cards read 237.7 to 118.8 s (cold, 2x faster), 230.1 to 73.3 s (models resident, 3.14x faster), 53.6 GiB (both stages; fits the Spark's 121, not the 5090's 31.84), and -38.3% / -3.2% (residency payoff: two-stage / native). The headline reads Same machine, 2x faster method, above a line reading MiniMax H3 Super Acceleration on DGX Spark.

Preface

A small kitchen makes you put the mixing bowls away before the roasting pans come out. A big counter lets both sit there all afternoon. The recipe does not change. What changes is how much of the afternoon you spend fetching and putting away.

Part 8 of the RTX 5090 series established the method: let MiniMax-H3 draft at 672x384, then let LTX-2.5 spend three steps refining the take you keep up to 1344x768. On a 5090 that beats running H3 natively at full size by 1.28x cold.

I ran the same workflow on a DGX Spark. Same graph, same weights, one quantization swap. The gap widens to 2.00x cold, and to 3.14x once both paths have their models loaded.

A naming note first, because these four terms are easy to run together. NVIDIA calls the method MiniMax H3 Super Acceleration and publishes it under Sol Engine, full name Sol Video Inference Engine. The port to a DGX Spark they call Sol-H3-Spark, and that is the line this article is on. The terms sit at different levels:

NameWhat it actually is
MiniMax H3 Super Accelerationthe method — H3 drafts small, LTX-2.5 refines
Sol EngineNVIDIA's acceleration framework, which the method ships under
Sol-H3-SparkNVIDIA's own build of that method for a DGX Spark, the one here
Sol-Attnan attention kernel you can use inside the refine stage

From here on it is just "two-stage", since what matters is the pipeline rather than which build you came in through.

One thing worth stating because it cuts against the obvious guess: the 672x384 draft is NVIDIA's own setting on the Spark, not something I picked. 896x512 is the draft size on their GB200 line; the two lines draft at different sizes. And 672x384 is not an arbitrary number: both lines output 1344x768, and the Spark line runs LTXVLatentUpsampler against the x2 upscaler — 672x384 doubled lands exactly on 1344x768. Going up from 896x512 is 1.5x, which is a different part. So the sigma 0.78 from the last article lines up with this one — if you follow the GB200 build at 896x512 instead, that value needs re-checking.

For a coordinate: NVIDIA report 6.852 s for a 5-second 1344x768 clip on a single GB200. ⚠️ That figure sums separately measured stages and excludes model loading and warmup, so it is not the same quantity as the submission-to-finish times in this article's table. Do not put them side by side.

The Spark is the slower machine at every step of this job. That is the interesting part.

118.8 s against 237.7 s, and 3.14x once the models stay loaded

Both paths produce the same thing: 1344x768, 124 frames, 24 fps, with audio. Four draft steps and three refine steps on the two-stage path, four steps at full resolution on the native path.

"Cold" and "warm" appear throughout and have nothing to do with temperature. Cold means the models were freed beforehand and this run reads them off disk. Warm means the previous run just finished and the models are still in memory.

Every number in the table is the whole workflow, submission to finish — draft sampling, the handoff, the upscale, refine sampling, VAE decode and writing the file. It is not the time the models alone spent computing. So the 45.5 s a warm run saves is not compute getting faster: the draft and the refine are both recomputed on the second run. What it saves is moving the models in and out of memory. I audit that node by node in the deep dive, because it is the claim in this article most worth doubting.

DGX SparkRTX 5090
Native H3 at 1344x768 (cold)237.7 s51.5 s
Native (warm)230.1 s41.5 s
Two-stage, H3 draft + LTX refine (cold)118.8 s40.3 s
Two-stage (2nd run, models still resident)73.3 s30.6 s

Every ratio below compares two paths on the same machine, two-stage against native. None of them compares one machine to the other.

  • Spark: 237.7 against 118.8 cold is 2.00x; 230.1 against 73.3 warm is 3.14x
  • 5090: 40.3 against 51.5 cold is 1.28x; 30.6 against 41.5 warm is 1.36x

The 672x384 draft, untouched. Stage one stops here. This is what goes into the refinement stage.

Native 1344x768 in four steps, 237.7 s. Same prompt, same seed — and not the same dog. The two paths take different sampling trajectories, so this is divergence rather than error.

All four Spark cells were taken with the GPU capped at 2200 MHz. That is not a choice: uncapped, a second consecutive native run takes the machine down, so the cell cannot be filled at all. The cap costs roughly 20% per run, but all four cells sit under the same restriction, so dividing them is clean. The next article covers the power loss.

One thing to be clear about first. Every Spark cell is 2.4-5.5x worse than the 5090 cell beside it. Two-stage costs 118.8 s on the Spark and 40.3 s on the 5090. The pipeline gets a bigger speedup on the Spark. The Spark itself is still the slower machine.

NVIDIA reports 56.17 s on the same machine. I measure 73.3 s.

The Sol-H3-Spark page quotes 56.17 s on a single DGX Spark, and it is explicit about what that covers: "from prompt arrival, including fresh Qwen encoding, to a completed MP4 with audio", warm. That is the same quantity as the numbers in my table — submission to file on disk, Qwen encoding and audio mux included. Their configuration matches too: a 672x384 draft at 124 frames in four steps, three refine steps, 1344x768 and 121 frames out.

So these are directly comparable. Theirs is 56.17 s, mine is 73.3 s, and I am 1.30x slower. I chased both reasons. One I could fix, one I cannot.

One: I did not have Sol-Attn installed, and adding it bought back 4%. The workflow asks for auto_sol_attn_conservative_exp, but there was no ComfyUI-SolAttn_triton on this box, so it quietly dropped to dense — the code path is literally called dense_fallback_sol_attn_not_loaded and raises nothing. Installed at the same commit the 5090 runs and measured again: warm goes 73.294 → 70.386 s, same seed, and the frames look the same side by side.

Four percent, not the 3.1x that page quotes — because the 3.1x is the kernel against FA4, and not many calls in a run qualify. The log is explicit about it:

[sol_attn] sparse (1, 16128, 32, 128) tau=1.0 bf16 pointer
[sol_attn] dense  (1, 16128, 32, 128): cross-attention (kept dense)
[sol_attn] dense  (1, 126, 32, 64): head_dim 64 != 128

Only head_dim-128 self-attention reaches the sparse path. Cross-attention stays dense by design, and the head_dim-64 calls do not qualify at all.

Two: the clock cap costs this pipeline 6%. Cap off, one warm run: 66.134 s, against 70.386 s capped.

(That 6% has to be measured on the two-stage pipeline itself. Native, within one session, goes 226 s to 246.6 s — 9%. The two workloads spend different amounts of time against the clock ceiling, so neither number scales to the other.)

Warm
Capped at 2200 MHz, no Sol-Attn73.294 s
Capped at 2200 MHz, with Sol-Attn70.386 s
Uncapped, with Sol-Attn66.134 s
NVIDIA, single Spark56.17 s

So 66.1 s against 56.17 s, still 1.18x, and I did not track it down. The two factors I could name account for part of the gap. The rest I do not know, and that is where I am leaving it.

⚠️ The four cells in the table below were measured without Sol-Attn, because that is the state you are in after following this article. If you want the 4%, install it yourself:

git clone https://github.com/kijai/ComfyUI-SolAttn_triton \
  ComfyUI/custom_nodes/ComfyUI-SolAttn_triton
git -C ComfyUI/custom_nodes/ComfyUI-SolAttn_triton checkout 26d816e

The T8 pack identifies a Sol-Attn implementation by AST-hashing its source, so a same-named package from a different source is not guaranteed to be accepted — which is why the commit is pinned above.

Nine weight files, two node packs, and a graph that has to be the -nogemma one

There is no new code here. T8mars's node pack implements the whole path inside ComfyUI, and the weights are two downloads.

Both repos are gated — you have to accept the terms in a browser before your account can download anything. Skip it and the hf download below returns a 401. Open coolthor/MiniMax-H3-pruned-NVFP4 and Lightricks/LTX-2.5 in a browser, accept the terms on each, then:

hf auth login

⚠️ The gate on the H3 repo is deliberate. MiniMax-H3's community licence excludes the EU, the UK, South Korea and the United States, and that restriction travels with the weights.

Everything on the H3 side is in one repo — both transformers, the text encoder, both VAEs, the turbo LoRA, the conditioning cache, the custom node and the workflow — and it is laid out as ComfyUI's models/ tree, so the download lands each file where it belongs instead of leaving you to match folders by hand. LTX-2.5 is the one thing fetched separately; its licence differs from H3's, so it is linked rather than mirrored.

hf download coolthor/MiniMax-H3-pruned-NVFP4 --local-dir ComfyUI/models \
  --include "diffusion_models/minimax_h3_fl2va*" "text_encoders/*" "vae/*" \
            "loras/minimax_h3_fl2v*" "conditioning_cache/*" "custom_nodes/*"

LTX-2.5 is a separate download under a different license:

hf download Lightricks/LTX-2.5 --local-dir ComfyUI/models \
  --include "diffusion_models/ltx-2.5-22b-distilled-transformer-nvfp4.safetensors" \
            "vae/ltx-2.5-*" "latent_upscale_models/*"

The first download lands a custom_nodes directory inside models/, which is the wrong place. Move it once:

mv ComfyUI/models/custom_nodes/ComfyUI-CondCache ComfyUI/custom_nodes/

Then the node packs. There are two, and the graph will not load if either is missing:

git clone https://github.com/T8mars/comfyui-minimax-h3-audio-T8 \
  ComfyUI/custom_nodes/comfyui-minimax-h3-audio-T8

git clone https://github.com/xmarre/ComfyUI-Spectrum-MiniMax-H3 \
  ComfyUI/custom_nodes/ComfyUI-Spectrum-MiniMax-H3
git -C ComfyUI/custom_nodes/ComfyUI-Spectrum-MiniMax-H3 checkout 4783a22

⚠️ Pin Spectrum at 4783a22. An older checkout throws native MiniMax H3 module is missing required helpers: time_shift_slope on ComfyUI 0.34.0 and stops the graph at the draft node. At least that one says something, unlike the failure in the next section.

The T8 pack carries the handoff with two nodes. MiniMaxH3SolEngineDraftToLTXT8Advanced trims frames and crops the aspect ratio before the draft is passed on, and MiniMaxH3SolEngineLTXIdentityRefinerSetupT8Advanced configures how the refine runs.

The second pack supplies SpectrumApplyMiniMaxH3, which node 7 of the graph needs. Miss it and the whole graph refuses to load, without telling you which node is missing.

LTXVLatentUpsampler needs no pack at all — the x2 latent upscaler ships with ComfyUI core.

You do not have to wire it yourself. This is the exact graph that produced every number in this article — 32 nodes, renumbered, no local paths in it:

⬇︎ minimax-h3-ltx-hybrid-refine-nogemma.json

Drag it into ComfyUI. The same file also sits under workflows/ in the Hugging Face repo, which is easier if you are pulling the weights anyway; the direct link above is for reading the graph before you request access.

⚠️ On a DGX Spark you have to use the -nogemma graph. The Gemma variant errors out on this machine. Details in the deep dive.

Two things to check yourself

One: confirm both custom nodes actually registered. LoadConditioningT is a custom node that is in no registry, so if the node pack did not load, the failure reads "node does not exist" rather than "file missing", and you will go looking for a weight file that is already there. Ask the server what it knows:

curl -s http://<your-spark-ip>:8188/object_info \
  | grep -o -E 'LoadConditioningT|MiniMaxH3SolEngineDraftToLTXT8Advanced|SpectrumApplyMiniMaxH3' \
  | sort -u

All three names have to come back. If any one is missing, the graph loads in the UI and then fails at queue time.

Two: confirm the refine schedule starts at 0.78. Not the official 0.909375, written 0.909 from here on. The full schedule is 0.78, 0.643, 0.546, 0. At 0.909 the refine stage stops sharpening the draft and redraws the face into a different person. That defeats the point of drafting first.

Get the versions wrong and the refine quietly hands you garbage

This section sits here because it is likelier to cost you a day than anything above it.

Single-stage H3 is fine on ComfyUI 0.30.x. The two-stage refine is not, and it will not tell you.

On 0.30.0 the refine returned status: success, exit code 0, a log with no errors, and a correctly shaped 1344x768 h264+aac file with 121 frames. Every frame was garbage — five seconds of pure black on the first day, colored noise when I reran the same graph the next morning.

Everything feeding it checked out. The H3 draft decodes to a clean picture. So does the upsampled latent one node before the refiner. The latent coming out of the refine has zero NaNs and a standard deviation of 0.80, which is exactly what a healthy latent looks like. So where is the damage? It correlates 0.235 with its own input — and that same input with noise added still correlates 0.74.

Same weights, same graph, same seed, run on an RTX 5090 that happened to already be on 0.34.0: correct clip. Matching the Spark to it fixed the Spark, and torch was never touched.

correct outputsilent garbage
ComfyUI0.34.00.30.0
comfy-kitchen0.2.310.2.26
ComfyUI-Spectrum-MiniMax-H34783a22 (2026-08-18)fcf2332 (2026-08-05)
torch2.13.0+cu1302.13.0+cu130

Take that column as one unit. The three are not independently selectable: ComfyUI 0.34.0 will not finish importing against comfy-kitchen 0.2.26, raising module 'comfy_kitchen' has no attribute 'int8_attention_is_available'. There is no configuration that isolates one package, so there is nothing to pin the blame on and no point looking.

⚠️ Do not reach for pip install -r requirements.txt --upgrade to get there. ComfyUI leaves torch unpinned in that file, so --upgrade can take your PyTorch and CUDA runtime packages with it. Install the pinned entries instead:

pip install comfy-kitchen==0.2.31 comfy-aimdo==0.4.15 \
            comfyui-frontend-package==1.49.6 \
            comfyui-workflow-templates==0.11.48 \
            comfyui-embedded-docs==0.5.10

Decode a frame before you trust a number. Every mechanical check passed on the broken runs — exit code, stream layout, resolution, frame count, duration — and once the failure shifted from black to noise, a black-frame detector passed too. If you are benchmarking this pipeline, look at a frame, or you are benchmarking a pipeline that produces nothing.

53.6 GiB of weights fit in 121 GiB, and that is the whole gap

Two stages means two complete model stacks. Nothing is shared between them.

Stage 1 — MiniMax-H3
  transformer                        11.67 GiB
  text encoder                       14.61 GiB
  video VAE                           4.85 GiB
  audio VAE                           0.56 GiB
  turbo LoRA                          1.82 GiB
                                    ----------
                                      33.5 GiB

Stage 2 — LTX-2.5
  transformer                        17.44 GiB
  video VAE                           1.35 GiB
  audio VAE                           0.34 GiB
  latent upscaler                     0.93 GiB
                                    ----------
                                      20.1 GiB

About 53.6 GiB of weights across both stages. Measured peak including working space is 104 GiB out of the 121 GiB available.

Memory capacity comparison: two-stage needs 53.6 GiB resident at once, 33.5 GiB for the MiniMax-H3 stage and 20.1 GiB for the LTX-2.5 stage; an RTX 5090 reports 31.84 GiB usable and cannot hold even the first stage; a DGX Spark reports 121 GiB and holds both, with a measured peak of 104
Figure 1: the 53.6 GiB line is what decides the fate of the same method on two machines. The 5090's 31.84 GiB does not even clear Stage 1's 33.5 GiB, so it swaps models on every run; the Spark's 121 GiB lets both stages sit there, and the second run reloads nothing.

An RTX 5090 has 31.84 GiB. (Both 31.84 and 121 are what my two machines report as usable, not the 32 GB and 128 GB on the spec sheets.) That is not enough for stage 1 on its own. So on a 5090 every single run is: load H3, draft, evict H3, load LTX, refine, evict. There is no state to carry into the next run, because there is no room to carry it in.

A DGX Spark's 121 GiB of unified memory holds both stacks with room left over. Load them once and they stay. The difference between the cold run and the second run is 45.5 s (118.815 minus 73.294), and most of that is the loading.

That is the mechanism behind the wider ratio. The Spark is slower at the compute, and the compute is most of what is left once you stop paying for loading.

Residency is worth 38.3% to two-stage and 3.2% to native

Two-stage's second run saves 45.5 s. Native's saves 7.6 s. That is the whole finding: residency helps the two-stage pipeline, not the machine.

ColdWarmChangeNodes reused
Native237.7 s230.1 s-3.2%10
Two-stage118.8 s73.3 s-38.3%18

Both paths reuse nodes, so "native has nothing to keep" is too simple an answer. What separates them by a factor of twelve is how much there is to load and what share of the run loading accounts for. Two-stage has to keep 53.6 GiB resident against native's 33.5 GiB, and native's 230-odd seconds go almost entirely into four sampling steps at 1344x768 — the 7.6 s of loading it saves is 3% of that. Two-stage's sampling is cheap by comparison, a 672x384 draft plus three refine steps, so loading is the larger share.

The 121 GiB buys native almost nothing, then, not because it has nothing to keep but because it has less to keep and its time was never going into loading in the first place.

ComfyUI reports which nodes it skipped: 18 of 32 on two-stage's second run. All 18 are loaders and configuration — nine model loaders, plus guiders, schedulers, setup nodes and the prompt.

What is not among them matters more. Both SamplerCustomAdvanced nodes re-ran, so the H3 draft sampling and the LTX refine sampling were recomputed from scratch. So were VAEEncode, both VAEDecode nodes, VAEDecodeAudio, the DraftToLTX handoff, the latent upsampler, and RandomNoise because the seed changed. The draft was redrawn. Every second of generation was paid for again, which rules out saved compute as the explanation for the 45.5 s.

The speedup is not the hardware being generous. It is that two-stage leaves far more worth keeping in memory, and spends proportionally less of its run computing.

The machine lost power twice, both on the second consecutive native run

Not a hang. Power loss. The kind where someone has to walk over and press the button.

It happened twice in one day, and both times it was the second back-to-back native 1344x768 run. The first native run completed fine at 202 s under full load. The second started with no gap and died about 90 s in.

Two-stage ran four times on the same machine with zero crashes, at a memory peak of 104 GiB — higher than the 74 GiB that was in use during both crashes. So memory pressure is not the variable.

Sustained-load duration is the candidate that fits. Native is 200 s of unbroken generation. Two-stage's longest continuous segment is 110 s, with lighter VAE and handoff stages in between.

This is not something the pipeline causes, and it has a fix: capping the GPU at 2200 MHz gets the same back-to-back pair to finish, at a cost of about 20% per run. A report on the NVIDIA developer forum describes hard lockups under sustained inference with the same driver version and the same model. How I tracked it down, and why a clock cap is what works, is the next article.

That said, with the clock capped native finishes too. Two-stage's stability edge is real, but a clock cap is the simpler fix — the reason to reach for two-stage is still the 2.00x.


Deep dive: what the 18 cached nodes were, and three departures from the 5090 build

Every number here was measured a second time

This article first went up on 2026-09-14 quoting 110.6 / 208.5 / 66.8 s and 1.89x. Those two-stage runs were on ComfyUI 0.30.0, and their output was broken — the silent garbage described above. The timings themselves were taken correctly, but comparing a pipeline that produces no picture against one that does is not a comparison, so the article came down and was redone.

Every cell in the table above now comes from a run on 0.34.0, and a frame from each of those runs was decoded and looked at. The four old figures are void; do not cite them.

You can run everything above without reading this. Nothing here changes the method or the commands. It is how the numbers were taken, the node-by-node audit behind the 18, and where this build differs from the one in the 5090 article.

The warm run is only a warm run if you change the seed

Every timing in this post is ComfyUI's /history endpoint: execution_success minus execution_start, divided by 1000.

Cold runs were preceded by:

curl -X POST http://<your-spark-ip>:8188/free \
  -H 'Content-Type: application/json' \
  -d '{"unload_models":true,"free_memory":true}'

Warm runs have a trap in them. My first attempt reused the seed and came back at 0.006 s with cached=31. Thirty-one of 32 nodes skipped: ComfyUI had recognised the identical graph and returned the previous output. That is a cache hit on the result, not a warm run of the pipeline.

Change the seed and the cached count drops to 18, which is the number the rest of this post uses.

The 18-node audit

Cached on the two-stage second run:

CountNode
4VAELoader
2UNETLoader
1CLIPLoader
1LoraLoaderModelOnly
1LatentUpscaleModelLoader
2BasicGuider
1KSamplerSelect
1BasicScheduler
1SpectrumApplyMiniMaxH3
1IdentityRefinerSetup
1LTXVConditioning
1LoadConditioningT
1prompt node

Nine of those are loaders. The other nine are configuration that depends only on the loaders.

The 14 that re-ran include both SamplerCustomAdvanced nodes, VAEEncode, VAEDecode x2, VAEDecodeAudio, the DraftToLTX handoff, LatentUpsampler, and RandomNoise. Everything that touches pixels or latents was recomputed.

Since the draft was redrawn, the 45.5 s cannot be saved compute. I attribute it to model loading, but that is an inference rather than a direct measurement — execution_cached reports that a node's output was reused, which is not the same as timing disk I/O or GPU residency. Pinning it down would need the setup and read phases timed separately.

Three differences from the RTX 5090 build

LTX-2.5 runs the nvfp4 checkpoint here, int8-convrot in the previous article. I checked whether that costs speed before swapping: n=3 warm runs on the 5090 gave a median of 30.574 s for nvfp4 against 30.819 s for int8, a difference of 0.245 s while the within-arm spread was 6.0 s. Indistinguishable on speed. I chose nvfp4 because it is 2.6 GiB smaller, and for no other reason.

Two-stage runs the no-Gemma variant, and on this machine that is mandatory rather than an optimisation. The stage-2 prompt is a single fixed string, so it is computed once and cached to a file, and the 14.32 GiB text encoder never loads. On the Spark the Gemma graph fails outright:

ValueError: not enough values to unpack (expected 4, got 1)
  sd1_clip.py:266

Line 266 sits in forward, which unpacks what process_tokens (line 172 of the same file) returns into four values, and on this machine gets one. A version mismatch between my ComfyUI and that code path is the obvious read, but I did not verify it. I did not find evidence that every Spark hits this — I can only say mine does. Swapping to the cached-conditioning graph steps around that call entirely, and the substitution is semantically equivalent rather than an approximation: I diffed the prompt that generated the cache and it is character-identical.

All four cells in the main table were taken at a 2200 MHz clock cap. That is not a preference. Uncapped, a second consecutive native run takes the machine down — both attempts are the power losses described above — so the cell cannot be filled at all. The cap costs roughly 20% per run, but it applies to all four cells equally, so the ratios between them are clean.

Two-stage's cold cell was measured twice, at 118.316 s and 118.815 s. The table uses the second.

Environment

Machine    ASUS Ascent GX10 (GB10), 121 GiB unified memory
OS         DGX OS, kernel 6.17.0-1032-nvidia
Driver     580.173.02
GPU clock  capped at 2200 MHz (nvidia-smi -lgc 300,2200)
ComfyUI    0.34.0, 1157 nodes registered
Packages   comfy-kitchen 0.2.31, comfy-aimdo 0.4.15, torch 2.13.0+cu130
Node pack  ComfyUI-Spectrum-MiniMax-H3 @ 4783a22
Output     1344x768, 124 frames, 24 fps, with audio
Steps      4 draft / 3 refine

Previous in the method: MiniMax-H3 + LTX-2.5 two-stage on an RTX 5090

FAQ

How much faster is the two-stage MiniMax-H3 + LTX-2.5 pipeline than native H3 on a DGX Spark?
Cold, with models freed beforehand, two-stage takes 118.8 s against 237.7 s for native H3 at 1344x768, which is 2.00x. With the models still resident both paths run again at 73.3 s and 230.1 s, which is 3.14x. Residency is worth 38.3% to two-stage and only 3.2% to native. The same pipeline on an RTX 5090 is 1.28x cold and 1.36x warm. Every Spark number was taken with the GPU capped at 2200 MHz.
Is a DGX Spark faster than an RTX 5090 for MiniMax-H3 video generation?
No. The Spark is 2.4-5.5x slower than a 5090 in every cell I measured. Two-stage is 118.8 s on the Spark against 40.3 s on the 5090. What is larger on the Spark is the two-stage method's payoff, 2.00x against 1.28x, not the machine's throughput.
Why does the two-stage pipeline benefit more from a warm cache than native does?
The second run reused 18 of the 32 ComfyUI nodes on two-stage and 10 on native. The two stages together are about 53.6 GiB of weights, which fits in the Spark's 121 GiB of unified memory, so the loaders stay resident between runs. An RTX 5090's 31.84 GiB cannot hold stage 1 alone at 33.5 GiB, so it reloads on every run regardless.
Does the warm run reuse the MiniMax-H3 draft video?
No. Both SamplerCustomAdvanced nodes re-ran, which means the H3 draft sampling and the LTX refine sampling were both recomputed. VAEEncode, both VAEDecode nodes, the handoff node and the latent upsampler also re-ran. Since the draft was redrawn, the 45.5 s the second run saves cannot be saved compute. Attributing it to model loading is an inference from which nodes were cached, not a separately timed measurement.
Which ComfyUI workflow file do I need to run this on a DGX Spark?
workflows/minimax-h3-ltx-hybrid-refine-nogemma.json, 32 nodes, shipped in the coolthor/MiniMax-H3-pruned-NVFP4 repo on Hugging Face. The Gemma variant errors out on this machine with ValueError: not enough values to unpack (expected 4, got 1) at sd1_clip.py:266, where forward unpacks the return of process_tokens into four values. The no-Gemma graph reads a precomputed conditioning tensor from disk instead. I have not confirmed this happens on every Spark, only on mine.
What sigma should the LTX-2.5 refine stage start at?
0.78, giving the schedule 0.78, 0.643, 0.546, 0. The official value is 0.909, and at that setting the refine stage redraws the face into a different person rather than sharpening the one the draft produced.
Did the DGX Spark crash while running these benchmarks?
Twice in one day, both times during the second consecutive native 1344x768 run, and both times the machine lost power entirely rather than hanging. Memory during the crashes was 74 GiB, lower than the 104 GiB peak that two-stage reached across four crash-free runs, so the variable is sustained-load duration rather than memory pressure. Capping the GPU at 2200 MHz stops it: the same back-to-back native pair then completes, at a cost of about 20% per run. The next article covers that in full.

Read next

Don't miss the next one

Subscribe, and you won't.

One-click unsubscribe anytime.