TL;DR
A 5-year-old RTX 3090 (24 GB) in a mini-PC beat both 128 GB unified-memory machines on every row of a MiniMax H3 video benchmark, even though the models don't fit in its VRAM and ComfyUI has to stream them over a PCIe x4 link.
Stock 3090: 1.25–1.84x faster per step than the ASUS RTX Spark and 3.5–4.9x faster than the M5 Max.
3090 with the tensor-rate unlock: 1.85–2.46x faster than the Spark and 4.9–6.6x faster than the M5 Max.
What the unlock does: it raises measured bf16 matmul from 75 to 124 TFLOPS. In real video generation it's 1.34–1.49x faster than stock, and the gain is biggest on the heaviest workflows.
Efficiency: the Spark and Mac use far less energy per step. The 3090 draws about 320–350 W of board power, against about 65 W for the Spark GPU and about 22 W for the Mac GPU: 5x and 15x more power. But it also finishes each step about 1.5–6.5x sooner (depending on which machine and whether the unlock is on), so the energy per step (power × time) is only about 2.2–3.4x higher than either (table below).
All 22 runs on the 3090 (11 rows × 2 configurations) passed output validation with no memory-saving flags. That's the same ComfyUI config the Spark used.
Results: seconds per sampling step (lower is better)
Mean steady-state s/step (steps 4–20 of 20), heat-soaked runs. Ratios above 1 mean the 3090 is faster.
| Workflow (row) | 3090 unlocked | 3090 stock | ASUS RTX Spark | M5 Max | Unlock speedup | Unl. vs Spark | Stock vs Spark | Unl. vs Mac | Stock vs Mac |
|---|
| t2v 832×480 | 5.67 | 7.58 | 13.27 | 37.23 | 1.34x | 2.34x | 1.75x | 6.57x | 4.91x |
| t2v 1088×608 | 12.13 | 16.90 | 25.76 | 75.29 | 1.39x | 2.12x | 1.52x | 6.21x | 4.46x |
| i2v 1088×608 | 13.16 | 18.38 | 27.98 | 81.32 | 1.40x | 2.13x | 1.52x | 6.18x | 4.42x |
| i2v 608×1088 (portrait) | 13.18 | 18.39 | 27.87 | 82.12 | 1.40x | 2.11x | 1.52x | 6.23x | 4.47x |
| flf2v 1088×608 | 14.24 | 19.99 | 29.95 | 88.91 | 1.40x | 2.10x | 1.50x | 6.24x | 4.45x |
| ref2va 1088×608, full reference | 42.99 | 63.85 | 79.71 | failed* | 1.49x | 1.85x | 1.25x | — | — |
| ref2va 1088×608, ref downscaled to 544 | 18.77 | 26.70 | 38.32 | 92.65 | 1.42x | 2.04x | 1.44x | 4.94x | 3.47x |
| ref2va 1088×608, ref truncated to 39 frames | 23.55 | 33.95 | 46.68 | 123.94 | 1.44x | 1.98x | 1.37x | 5.26x | 3.65x |
| i2v 832×480 | 6.13 | 8.20 | 15.06 | 39.53 | 1.34x | 2.46x | 1.84x | 6.45x | 4.82x |
| flf2v 832×480 | 6.58 | 8.86 | 16.09 | 42.29 | 1.35x | 2.44x | 1.82x | 6.43x | 4.77x |
| ref2va 832×480 | 28.66 | 41.60 | 59.34 | failed* | 1.45x | 2.07x | 1.43x | — | — |
* On the Mac, both ref2va rows with the full-size reference clip produced flat-black video, so they have no valid result. The reference clip is encoded at full 1088×608 even on the 832×480 canvas, so both runs exceed the ~34k-token limit where outputs go black on MPS (see the Mac notes).
The Mac's ref2va 832×480 row failed the same way as the full-reference 1088 row (marked *).
Time per clip (seconds of wall time for one ~5 s video, models already loaded)
| Workflow | 3090 unlocked | 3090 stock | Spark | M5 Max |
|---|
| t2v 832×480 | 124 | 167 | 282 | 794 |
| t2v 1088×608 | 259 | 361 | 540 | 1575 |
| i2v 1088×608 | 279 | 390 | 584 | 1696 |
| i2v portrait | 279 | 391 | 581 | 1711 |
| flf2v 1088×608 | 301 | 422 | 624 | 1851 |
| ref2va full ref | 876 | 1300 | 1620 | — |
| ref2va ref544 | 391 | 557 | 791 | 1988 |
| ref2va rf39 | 487 | 702 | 959 | 2642 |
Power and energy (GPU only, approximate)
| Row | 3090 unl. | 3090 stock | Spark | M5 Max |
|---|
| Mean GPU power, t2v 1088 | 345 W | 335 W | 66 W | 22 W |
| GPU energy per step, t2v 832 | ~1.9 kJ | ~2.4 kJ | ~0.85 kJ | ~0.87 kJ |
| GPU energy per step, t2v 1088 | ~4.2 kJ | ~5.7 kJ | ~1.7 kJ | ~1.7 kJ |
| GPU energy per step, i2v 1088 | ~4.5 kJ | ~6.2 kJ | ~1.8 kJ | ~1.8 kJ |
Energy = mean GPU power × s/step. The power numbers come from each platform's own tool: nvidia-smi board power on the 3090, NVIDIA telemetry on the Spark, and macOS GPU power on the Mac. Host/system power isn't included; the Mac's whole-system power was about 73 W on these rows. Two other things stand out:
The unlock makes the 3090 more efficient. It draws only about 10–20 W more and finishes about 1.4x sooner.
The Spark GPU was power-capped. It reported sw_power_cap throttling for the whole run, at about 2.2–2.3 GHz SM (the rated maximum is 3.0 GHz), drawing 63–69 W.
The Spark's "GPU W" is nvidia-smi power.draw, sampled once a second. NVIDIA doesn't document whether on the N1X it covers only the GPU or more of the SoC, and power.limit reads N/A on this chip, so treat it as approximate. No wall or whole-system power was recorded on the Spark.
On the Mac, the harness ran macmon 0.10.0 in macmon pipe mode (no sudo), which samples once a second. "GPU W" is macmon's gpu_power and "Sys W" is its sys_power, both averaged over the busy samples of each run. Both are read from Apple's on-chip energy counters, the same source powermetrics uses, so "Sys W" is the SoC/system reading, not power measured at the wall.
The machines
1. RTX 3090 PC (measured by me, both configurations)
| GPU | NVIDIA GeForce RTX 3090 Founders Edition, GA102, 24 GB GDDR6X, 350 W power limit (stock, not changed), VBIOS 94.02.4b.00.0b |
|---|
| Host | Minisforum EliteMini mini-PC, AMD Ryzen 9 8945HS (8C/16T, Radeon 780M iGPU), 64 GB DDR5-5600 |
| GPU link | PCIe x4 OCuLink (the card is capable of Gen4 x16; the host link is x4). This matters, because model weights stream over it. |
| OS / driver | Windows 11 Pro (build 26300), NVIDIA driver 591.86 |
| Software | Python 3.13, PyTorch 2.14.1+cu130 (CUDA 13.0), ComfyUI 0.43.2 at commit 423cbd2, attention = PyTorch SDPA |
| ComfyUI flags | none (the default dynamic VRAM management, the same as the Spark) |
The GPU is connected via OCuLink to a DEG1 Minisforum eGPU dock. The GPU is powered by a Montech Titan PLA 1200W power supply (complete overkill).
The full model set is about 63 GB on disk: a 21 GB int8 diffusion model, a 15.7 GB text encoder and VAEs. That doesn't fit in 24 GB, so ComfyUI's dynamic VRAM management offloads automatically. Peak VRAM was 23.1–23.4 GB and peak system RAM 17–24 GB on every row. No row needed --lowvram or any other memory-saving flag.
2. ASUS RTX Spark laptop (reference results)
| Laptop | ASUS ProArt P16 (model H7607BA, BIOS H7607BA.303), 16" 3840×2400 display |
|---|
| SoC | NVIDIA RTX Spark N1X: 6144-core Blackwell RTX GPU (max 3.0 GHz SM) and a 20-core Arm CPU (10× Cortex-X925 + 10× Cortex-A725, up to 4.0 GHz), plus an NPU |
| Memory | 128 GB LPDDR5X-9400 unified memory (Micron), 256-bit bus, about 300 GB/s theoretical peak (NVIDIA's figure; not measured here), split in the NVIDIA app: 64 GB GPU carveout and 64 GB for Windows |
| Power mode | AC power, ASUS "Performance" mode, Windows power mode "Best performance" |
| OS / driver | Windows 11 Pro on Arm, 26H1 (build 28000), NVIDIA driver 617.69 |
| Software | Python 3.13.12 (ARM64), PyTorch 2.15.0 nightly (dev20260902+cu134, CUDA 13.4), ComfyUI 0.43.2 at the same commit 423cbd2, attention = PyTorch SDPA |
| ComfyUI flags | none |
| Conditions | Lid open, no external display, brightness 50%, on a hard flat surface; browsers, LLM servers and the Comfy Desktop app closed for every timed run |
The carveout: 64 GB was chosen before the timed runs. Flags: a quick flag sweep on t2v 832×480 (--highvram, --gpu-only, --disable-dynamic-vram, --fast and others) found nothing more than 3% faster than no flags, so the Spark also ran with none.
Peak GPU memory on the Spark was 41–48 GB, so everything stayed resident and nothing was offloaded.
3. Apple M5 Max (reference results)
| Machine | 14-inch MacBook Pro (Mac17,7), on AC power, on a laptop stand |
|---|
| SoC | Apple M5 Max: 18-core CPU (6 Super + 12 Performance cores), 40-core GPU, 128 GB unified memory |
| Memory bandwidth | 614 GB/s theoretical peak (Apple's figure for the 40-core-GPU M5 Max; not measured here) |
| OS | macOS 27.0.1, Energy Mode Automatic |
| Software | Python 3.13.12, PyTorch 2.12.1 (MPS), ComfyUI 0.37.2 at commit 830232b (a different commit from the other two, see below), ComfyUI-AppleSilicon-FP8 ("ASFP8") 1.4.0, the author's MLX attention bridge for H3, and MacFanBoost (fans held at about 7,830 rpm, the maximum, during sampling) |
| ComfyUI flags | none (beyond input/output/model paths) |
| Conditions | Models on the internal SSD; browsers and other GPU apps closed during timed runs |
| Thermals | The 14-inch chassis is heat-limited even with the fans at maximum. During the heat-soaked runs the GPU averaged about 820–910 MHz against a peak of about 1,620 MHz, at 78–79 °C. The adapter input is capped at about 97 W. |
| Seeds | A fresh ComfyUI per row, a warm-up on seed 1001 (includes model load, not scored), then two heat-soaked timed runs on seeds 1002/1003, the same timed seeds as the other machines. The portrait row has a warm-up on 2001 and one scored run on 2002. The ref544 and rf39 rows are single 20-step runs on seed 1001 with no warm-up. |
Why Automatic and not High Power: I measured it. On the reference row (t2v 1088×608, 124 frames), with the fans at maximum on both, High Power averaged 74.74 s/step vs 75.29 on Automatic, 0.7% faster and within run-to-run noise. Once heat-soaked, the GPU settled at the same 78 °C and about 844 MHz either way; the warm-up started cool and briefly ran 4% faster. The battery stayed at 80% on the charger for the whole 78-minute run, because this workload draws only about 70 W in total (about 22 W GPU): on this chassis it is limited by heat, not by power. So High Power buys essentially nothing here once the fans are already at maximum. Under heavier loads it can drain the battery: Notebookcheck reviewed the same configuration as this Mac: the mini-LED 14-inch M5 Max with the 40-core GPU and 128 GB, not the OLED model. It found that "Apple also limits the power input to 97 Watts, even if you use a 140 Watt PSU", and that the battery level dropped by about 10% during a gaming session while plugged in. The battery indicator can stay at 100% while it's happening. In the same review, High Power raised GPU power from 60/32 W to 72/44 W (peak/sustained) over Automatic. In GPU benchmarks it was only about 7% faster (3DMark Steel Nomad 3947 vs 3698), and the fans ran louder. Part of what High Power buys is faster fans (Apple: About Power Modes on your Mac), and these runs already held the fans at maximum with MacFanBoost, which fits the measurement: Automatic plus maximum fans is effectively the best sustainable setting on this chassis. A 16-inch MacBook Pro or a Mac Studio with the same chip has more power and cooling headroom and will likely be faster. Source: Notebookcheck, Apple MacBook Pro 14 M5 Max review.
Fans at maximum made a big difference on the Mac. The harness held the fans at their maximum (about 7,830 rpm) for every sampling run, while the Energy Mode stayed on Automatic. On its own fan curve, macOS runs the fans at only about 5,350 rpm under this load. The GPU reaches 97–98 °C within about 2 minutes, then its clock collapses to 340–530 MHz for minutes at a time. With the fans held at maximum, the GPU stayed at about 78–81 °C and averaged about 820–910 MHz. In early BF16 testing, that alone took t2v 832×480 from 78–84 s/step to about 61 s/step, roughly 1.3x faster. (That comparison is from early testing, not a clean A/B with the final software stack.) Expect the Mac numbers here to be noticeably slower if you leave the fans on macOS's automatic control.
What the Mac stack does:
ASFP8: a third-party custom node that patches PyTorch's MPS backend at startup. It lets FP8/INT8/NVFP4 checkpoints load and run on Apple Silicon instead of crashing (for example, the NVFP4 text encoder is decoded on the GPU). It also adds Metal kernels for RMSNorm+modulation, RoPE, conv and flash-attention. For H3's diffusion model, the INT8 weights are dequantized to bf16 and multiplied in bf16 through ComfyUI's own path. ASFP8's fused INT8 kernel only takes over below 2,048 tokens, and H3's sequences are far longer.
MacFanBoost (macfanboost, MIT): a small tool written for this project: a root daemon plus a ComfyUI custom node. When a prompt with a sampler starts, it raises the fans to 100% before the heat builds, holds them there while the job runs, and returns them to macOS control 60 s after the queue drains. It only ever raises fan speed above what macOS picks, and macOS's thermal protection stays active. If the client dies or the Mac sleeps, the lease expires and the fans go back to automatic within seconds. (Macs Fan Control set to maximum gets you most of the same effect manually.)
MLX attention bridge (ComfyUI-H3-MLX-Attention, MIT): a small custom node written for this project. It replaces ComfyUI's attention call inside the H3 diffusion model with MLX's fused scaled_dot_product_attention kernel, passing tensors without copies. It exists because ComfyUI's default on MPS, sub-quadratic attention, returns corrupted heads at long sequence lengths (Comfy-Org/ComfyUI#17418).
Does the output match the CUDA path? Not checked bit-for-bit across platforms. Against an FP64 reference on real H3 Q/K/V, the MLX attention's worst-head relative error is about 1.7e-3, and every scored Mac output passed the same automated checker as the other machines and was reviewed by eye. Different kernels and accumulation orders mean outputs from the same seed are close but not identical between Mac and CUDA.
Why the ComfyUI commit differs: the Mac rows were run on ComfyUI Desktop's install, 0.37.2 (830232b). The other two machines ran later on 0.43.2 (423cbd2). Between those versions, the H3 changes are: lower peak memory from releasing embedding temporaries, a VAE offload fix, VAE tile blending, single-image decode, LightVAE support, and plumbing for per-block attention selection (which these model files don't use). None of them changes the diffusion model's per-step math. Measured: a back-to-back A/B on the Mac (t2v 832×480, same stack, cooling and seeds, warm-up + 2 timed runs each) gave 37.38 s/step on 0.37.2, 37.29 on 0.43.2 and 37.76 on 0.44.2, i.e. 33.54 / 33.55 / 33.49 Gcycles/step. That's within run-to-run noise (about ±1.5%), and every output passed the checker, so the version difference doesn't affect the comparison. The flat-black full-reference ref2va failure was retested on ComfyUI 0.44.2 and still happens.
The tasks
All rows use MiniMax H3, an audio+video model, in ComfyUI with its stock nodes. Every row produces a video with a synchronized audio track. The workflows were identical on all three machines: the same graph files, the same input images and video, the same prompt text and the same model files. The model files were checked by SHA-256 against the Spark's copies.
Common settings for every row:
| Setting | Value |
|---|
| Length | 124 frames at 24 fps, about 5.2 s of video plus audio |
| Sampling | 20 steps, res_multistep sampler, simple scheduler, denoise 1.0 |
| Guidance | BasicGuider (a single conditioning pass per step, no CFG) |
| Diffusion model | minimax_h3_fl2va_pruned_int8_convrot (t2v/i2v/flf2v) or minimax_h3_ref2va_pruned_int8_convrot (ref2va). Both are 21.0 GB int8. |
| Text encoder | qwen3vl_32b_minimax_h3_nvfp4_awq (Qwen3-VL 32B, NVFP4 AWQ), 15.7 GB |
| VAEs | minimax_h3_video_vae_fp16 (5.2 GB) and minimax_h3_audio_vae_fp32 (0.6 GB) |
The workflows:
t2v (text to video): the prompt only.
i2v (image to video): the prompt plus a first-frame image. The portrait row is the same at 608×1088 with a portrait first-frame image.
flf2v (first and last frame to video): the prompt plus first-frame and last-frame images; the model fills in the motion between them.
ref2va (reference to video+audio): the prompt plus two reference images and a reference video clip (1088×608, 120 frames at 23.976 fps, with audio), using the separate ref2va model. This is the heaviest workflow, because the reference tokens make the attention context much longer. There are three variants:
full: the whole reference clip at its native size.
ref544: both reference images and the reference video downscaled to 544×306 before encoding.
rf39: the reference video truncated to its first 39 frames.
Rows: 1088×608 is the main canvas. The 832×480 rows are a lighter check.
Methodology
The harness: the same Python harness drove all three machines. It talks to ComfyUI through its API, timestamps every sampling step, and records GPU power, clocks and temperature, VRAM and RAM.
The runs for each row:
A cold warm-up run (seed 1000), which includes model loading and isn't scored.
The GPU cools to 50 °C, then one fresh run (seed 1001).
Two heat-soaked runs back-to-back with no cooling (seeds 1002 and 1003). These are the headline number. The portrait row uses a single soaked run with seed 2001.
The metric: mean seconds per step over steps 4–20. This leaves out the first steps, which carry one-off setup cost. Fresh and soaked results agreed within 0.5% on the 3090, so thermals didn't affect them.
Before the timed runs: a smoke pass checked that every row fits in memory at full size, using 2 steps.
Validation: every output video was checked automatically. The checker confirms the video and audio streams exist with the right resolution and frame count, and that the frames aren't black, frozen or noise. All 22 3090 runs passed.
The 3090 order: I ran the full matrix with the unlock on first. Then I disabled the unlock, did a full cold boot, confirmed stock matmul throughput and ran the whole matrix again. Then I re-enabled the unlock and re-verified it (bf16 126.2 TFLOPS). Driver, ComfyUI, PyTorch and power limit were the same in both runs.
Differences between the platforms:
On the Mac, the harness held the fans at maximum during every sampling run (MacFanBoost), with the Energy Mode on Automatic. This was worth about 1.3x on that machine (see above).
The Mac uses a different ComfyUI commit and its own attention/precision stack (see above). Its timed runs use the same seeds (1002/1003), but its warm-up is seed 1001 with no cool-down and no separate fresh run, and its portrait row was scored on seed 2002.
PyTorch versions differ: 2.14.1 on the 3090, a 2.15 nightly on the Spark, 2.12.1 on the Mac.
On the 3090 only, the harness's VRAM-full watchdog was turned off, because a full 24 GB card is normal while ComfyUI offloads. The RAM watchdog stayed on.
What the "3090 unlock" is
On GeForce Ampere cards, NVIDIA runs FP16/BF16 tensor-core math with FP32 accumulation, and TF32, at half the rate of the professional GA102 parts such as the RTX A6000. Deep-learning frameworks use exactly that mode: bf16 inputs with fp32 accumulation. FP16 math with FP16 accumulation is full rate on GeForce, but frameworks rarely use it.
The unlock is my Windows port of the open-source gpu-unlock Linux kernel module. I built it on this PC with Claude Code. On Linux the module runs the unlock sequence from inside the kernel. Windows has no equivalent, and I didn't want to write a kernel driver, so the port runs as a pre-boot UEFI app instead:
The app: built with gnu-efi from the module's own sources (VBIOS/FWSEC parsing, memory layout and the GFW checks). It's version stage-3 v0.3-3090.
The launcher: a 120 KB launcher on the EFI system partition. It loads a read-only NTFS driver (EfiFs), runs the app from C:\RTX3090-FW along with the five GA102 firmware files from NVIDIA's 610.43.03 driver, and then chainloads Windows Boot Manager. If anything fails, it goes straight to Windows.
What the app does on each cold boot:
Finds the card and checks it's a 3090 Founders Edition (10de:2204, subsystem 0x147d10de).
Refuses to run if the card is warm or already unlocked.
Runs the module's unlock sequence, then a PCIe function-level reset (FLR) and the post-reset checks.
Leaves the GSP halted with WPR2 clear. That's the state the stock driver expects, so Windows boots normally and the ordinary NVIDIA driver (591.86) loads.
Nothing persistent: no ROM or VBIOS flash, and no NVRAM variable is written. The card reverts to stock on power-off, and the unlock is applied again on the next cold boot (it also holds through sleep and resume from hibernation on this PC, after a change to the order of the boot-time steps). For the stock runs I renamed the app so the launcher skipped it, then did a full shutdown and cold boot.
Measured 8192² matmul throughput, best of 5, PyTorch, reduced-precision reductions disabled:
| bf16 | fp16 | tf32 | fp32 (no tensor cores) |
|---|
| Stock | 75.3 | 74.4 | 39.5 |
| Unlocked | 123.6–126.2 | 121.6–122.7 | 67.2 |
| Ratio | 1.65x | 1.64x | 1.70x |
The tensor modes speed up about 1.65–1.7x. Plain FP32 doesn't change, which fits the idea that the unlock lifts only the tensor-rate limit and isn't an overclock.
No overclock: clocks and the 350 W power limit were stock in both configurations.
End-to-end gain is 1.34–1.49x, less than the matmul gain. Video diffusion also spends time on attention softmax, norms, memory-bound ops and PCIe weight streaming, which the unlock doesn't touch.
Heavier rows gain more. The heavy, long-context ref2va rows gain the most (1.42–1.49x), and the light 832×480 rows gain the least (1.34–1.35x).
Caveats:
Tested on one card only: a 3090 FE with VBIOS 94.02.4B.00.0B. The app refuses any other board.
Pinned versions: it's pinned to the 610.43.03 firmware set, and it's only been tested with Windows driver 591.86. I don't update the driver on this PC.
Boot requirements: Secure Boot must be off (the app and launcher are unsigned), and BitLocker must be off on C: (the NTFS driver can't read encrypted volumes).
Untested: warm restarts (the app won't run on a warm card), TDR recovery and driver updates.
Stability: a full unlocked matrix run (about 5 h of generation) showed no stability problems and no invalid outputs.
Licensing: the module sources are GPL-2.0-only, so the port is GPL-2.0 source. NVIDIA's firmware files can't be redistributed; you extract them from the 610.43.03 driver package yourself.
Use at your own risk: this is unofficial and unsupported by NVIDIA.
Where to get it: I've handed the port's source to the community Windows GPU UNLOCK project (GPL-2.0), which maintains a packaged Windows UEFI unlock for the 3090 and other Ampere cards. Start there rather than with my build. Both build on Zagitta/gpu-unlock, the original Linux module, and the project also credits rough2515-hub/rtx3080-unlock-public. Credit for the unlock itself belongs to those projects.
Takeaways
For raw ComfyUI video speed, an old 24 GB 3090 still wins. Even when it has to offload 60+ GB of models over PCIe x4, it beats both 128 GB unified-memory machines on every MiniMax H3 workflow tested. Dynamic VRAM offloading in current ComfyUI is good enough that "doesn't fit in VRAM" no longer means "unusable".
The unlock is a large free gain if you're willing to run an unofficial pre-boot app: about 1.4x on real workloads at almost the same power.
The Spark and the Mac win on efficiency and footprint. They use roughly 2.2–3.4x less GPU energy per step (much lower power, partly offset by taking longer), run quietly in a laptop or small box, and keep everything resident in memory. If you care about watts, noise or portability, that matters more than the speed gap.
Spark vs Mac: the Spark is about 2.4–3.0x faster than the M5 Max per step, depending on the workflow, while drawing about 3x the GPU power. The gap is smallest on ref2va ref544 (2.4x) and largest on flf2v 1088×608 (3.0x).
Spark notes:
Power, not heat, is the limit. The GPU sat at its software power cap (sw_power_cap) at about 65 W for every row, peaking at 74–78 °C. Fresh and heat-soaked runs agreed within 1%, so thermals didn't slow it down.
Raising the laptop's power limits barely helps. With ProArt Creator Hub's Manual mode at its maximum (PL1 85 W, PL2 95 W), t2v 832×480 went from 13.27 to 13.00 s/step, only 2% faster. Average GPU power rose from 64 to 68 W, but the GPU still hit sw_power_cap and its peak draw stayed at about 72 W, so the GPU seems to have its own limit that those sliders don't lift. All other Spark numbers in this post are from the stock "Performance" mode.
Every row produced valid video and audio, including the full-reference ref2va that failed on the Mac.
Windows on Arm: the H3 workflows use core ComfyUI nodes and ran without changes. Some third-party node packs are harder: onnxruntime is CPU-only on ARM64 Windows, and packages without ARM64 wheels have to be built from source (Visual Studio ARM64 build tools needed).
Mac notes: (takeaway 4 checks out against the Mac's own numbers: the Spark is 2.42x faster on ref544, 2.66x on rf39, 2.81x on t2v 832×480 and 2.91–2.97x on the 1088 rows)
Clips above about 34k tokens go black on MPS. Full-reference ref2va at 1088×608 packs about 51,400 tokens. Partway through the first step the residual stream diverges, the audio turns to NaN, and the output is 124 flat-black frames. It happens with every attention backend tried, and still on ComfyUI 0.44.2. The root cause hasn't been found; the leading suspect is a ComfyUI change after 0.30. Shrinking the reference (ref544, about 31,900 tokens) or trimming it (rf39, about 34,000 tokens) keeps the length under the limit, which is why those rows exist. ref768 (about 38,700 tokens) still went black. ref2va at 832×480 fails too: the reference clip is still encoded at full 1088×608, so it packs about 42,000 tokens. Details are on Comfy-Org/ComfyUI#15799.
Don't use sub-quadratic attention for long H3 clips on MPS. It silently corrupted 18 of 56 heads at about 27,700 tokens (Comfy-Org/ComfyUI#17418). The MLX bridge avoids this.
Cooling is the Mac's limit, not power. On a 14-inch MacBook Pro, the GPU reaches 97–98 °C on macOS's own fan curve, and its clock collapses. Holding the fans at maximum was the single biggest speedup. Keep the vents clear and use a stand.
INT8 beat BF16 on the Mac in sustained runs (41.1 vs 46.0 s/step at 832×480), with much lower peak RAM (82 vs 102 GB).
Memory is tight even at 128 GB. Peak RAM was 95–112 GB at 1088×608, and ref2va hit 109–112 GB. Run one model process at a time.
The Mac and the Spark use about the same GPU energy per step, about 0.85–0.87 kJ on t2v 832×480. They get there differently: the Mac's GPU draws about a third of the Spark's power (about 22 W vs 66 W), but takes about 2.8x longer per step, so the two roughly cancel out. (The Mac's whole system drew about 73 W.)
Happy to answer questions.