mac mini 24gb success story

#4
by hololabs - opened

Community Feedback: Mac Mini M4 (24GB) Performance & V2 Update Findings

Hey! We've been heavily testing the new mmh3-turbo-clipproj4b-fl2va-v2-q4tp.cmf update on a Mac Mini M4 (24GB Unified Memory). Here are our complete findings regarding the V2 split-projection update, memory limits, and optimizations.

1. The V2 Update is a Massive Success

The split-projection layer completely solved the "Picasso-melting" issue.
Previously, on the 14GB Draft model, characters' faces would instantly smear or deform by frame 12 during movement. With the V2 patch, the identity and facial structure remain perfectly locked in. We get 25GB-level face consistency at 14GB generation speeds. This makes Draft Mode completely viable for actual production testing!

2. The 24GB Unified Memory "Sweet Spot"

Because the cortiq engine loads the model, DiT activations, KV cache, and the uncompressed video block into the same memory pool, the 24GB RAM limit creates a very strict ceiling before the system violently drops into SSD Swap Memory (which causes severe "Swap Thrashing" and stalls the GPU down to 0 Watts).

Safe Limits for 24GB M4 Mac Mini:

  • High Quality / Cinematic Model (25GB):
    • 512x256 (Standard): Safe up to ~70-90 frames.
    • 768x448 (High-Res): Hard cap at 40-50 frames. Attempting 90 frames at this resolution pushes RAM to 22.2GB and Swap to 1.1GB, causing the GPU to stall and the generation time to balloon.
  • Draft V2 Model (14.5GB):
    • Because the model is 10GB smaller, it is much more forgiving with frame limits, but 448x768 at 90 frames is still the absolute physical threshold before memory paging begins. 50 frames at 448x768 is the golden sweet spot (averaging a blistering 136 seconds per step).

3. The VAE CPU Bottleneck (Reference Images)

When using a --first-frame reference image, the Video VAE Encoder runs entirely on the CPU (E-Cores at 100%, P-Cores asleep). This adds a massive ~100 second penalty to the start of the generation (e.g., encode 0/1 (140.8s)).
When doing pure Text-to-Video without a starting frame, this step drops to 0.1s. If Metal GPU shaders are ever implemented for the VAE's 3D-conv layer, generation times for Image-to-Video will drop significantly.

4. Bypassing the Strict mm_kill Timeout (100% GPU Success)

The qtensor.rs timeout budget (239ms) is currently too strict for the massive integrated multimodal prompt matrix multiplications. The engine kept falsely throwing the device contended, CPU for the rest of the process warning and falling back to the CPU.

Our Hack: We modified crates/cortiq-engine/src/gpu.rs to hardcode mm_killed() to false and gutted mm_kill().
The Result: Flawless success. The denoise loop ran at 100% GPU utilization (15.6W) without a single crash or graphical glitch. The engine successfully chewed through 50 frames of 448x768 in just 9 minutes. The fallback logic is overly aggressive for standard desktop use!

5. Lifting the Apple Metal Limits (Sysctl)

Apple Silicon artificially limits Metal buffers to ~13.6GB. To run the 25GB Cinematic Model, users must run sudo sysctl iogpu.wired_limit_mb=... to allocate more RAM to the GPU. Without this, the engine fails to map the model into memory. We highly recommend adding a warning or helper script in the documentation for Mac users so they know they need to manually lift this limit!

anime cooking clipi

same script but photo realism

Both halves of this report are in cortiq 0.5.80 (out now: cargo install cortiq-cli, or the release binaries):

  • The mm_kill hack is no longer needed. The contention kill is disarmed for the whole prompt-encode phase and arms only when the denoise loop starts β€” the encoder is a one-shot pass over 12 GB, and on a 24 GB box it streams from disk for reasons that are not contention. Three consecutive strikes are still required after that. CMF_MM_KILL=0 remains as the big switch.
  • P-cores for the keyframe encode. Your asitop (E-cores at 100%, P-cores asleep during the --first-frame VAE encode) was the pool's worker threads landing wherever the scheduler put them; they now ask for QOS_CLASS_USER_INITIATED. That shortens the ~100–140 s encode; a device path for the encoder's 3-D convolutions is the real fix and is on the list.
  • Your frame budgets are in the model card (Field notes): 25.7 GB file β€” 512Γ—256 safe to ~70–90 frames, 768Γ—448 caps at 40–50; v2 14.5 GB file β€” 448Γ—768 Γ— 50 frames at 136 s/step, 90 frames is the paging edge. And the v2 face-consistency confirmation, in your words.

Thank you β€” please break it again.

Cortiq v0.5.82 Field Report: I2V Pipeline & Memory Stress Testing

Hardware: Apple Mac Mini (M4, 24GB Unified Memory)
Model: mmh3-turbo-clipproj4b-fl2va-v2-q4tp.cmf (14.5 GB)
Resolution: 768x448

1. Validating the v0.5.82 Upgrades

The latest adjustments to core scheduling and contention detection are working exactly as intended. We ran several Image-to-Video (--first-frame) benchmarks to validate the pipeline:

  • P-Core Wakeup (QOS_CLASS_USER_INITIATED): Successfully verified. During the massive 12GB prompt-encode phase, macOS properly routed the workload. asitop readings showed P-cores pinned at 100% @ ~3900 MHz, while E-cores hovered around 70-96%.
  • mm_kill Disarmament: The engine no longer throws false-positive contention kills during the heavy initial VAE encode. The 164–174 second image encode phase completes smoothly, allowing the engine to successfully transition into the denoise loop.
  • Performance Parity: For a 39-frame I2V generation, the overall denoise speed stabilized at ~18.0 seconds/step. This perfectly matches our historical averages for standard Text-to-Video runs, meaning the engine is absorbing the heavy I2V encode overhead without degrading overall batch performance.

2. Pushing the "Paging Edge" (How We Break It)

We specifically set out to test your hypothesis regarding the memory paging edge. While you estimated the edge to be around 90 frames for the 14.5 GB v2 model, our telemetry suggests the true cliff for a 24GB machine is much lowerβ€”likely right around 50 frames.

The "Nuke Test" (120 Frames)
To completely break the engine, we launched a 120-frame I2V generation. Here is the lifecycle of the system collapse:

  1. Encode Phase: Survived. RAM sat comfortably at ~5.7GB.
  2. Transition to Denoise: As the engine allocated the massive 120-frame latent tensor, the system instantly flatlined into swap death.
  3. Telemetry at Collapse:
    • Physical RAM: 22.0 / 24.0 GB
    • Swap: 4.0 GB used / 5.0 GB capacity (macOS forcefully doubled the swap capacity in real-time to prevent a kernel panic).
    • GPU Usage: Plummeted from ~77% down to 53% (and falling) as the cores starved waiting for data to be dragged across the swap boundary.

We manually bailed out (SIGINT) right as denoise 1/4 began to spare the SSD, so we didn't wait to see if the 3-strike mm_kill would formally execute the process. However, the system was undeniably thrashing.

Conclusion:
The 0.5.82 engine is remarkably stable and fast. 40-frame runs are the undisputed "sweet spot" for 24GB hardware (~20.1GB RAM used, 0.9GB swap). Pushing beyond 50 frames invites steep swap penalties, and 120 frames is a guaranteed system stall.

Thank you for the excellent update!

"Claire's Day"

Your 0.5.82 report is in the model card now, including the correction: I had estimated the paging edge at ~90 frames for the 14.5 GB file and you measured ~50 β€” the card says 50. The I2V number (18.0 s/step at 39 frames, 768Γ—448, parity with T2V) is there too, and so is the collapse profile at 120 frames.

0.5.92 adds runtime adapters (#8) β€” worth a try on the faces: fal's Realism adapter is attention-only, so all 104 of its branches bind, and on my M4 it costs about a tenth of a step.

Follow-up with a cleaner measurement, because the first one was taken on a machine that was swapping.

With memory freed and the two runs back to back β€” 512Γ—288, 22 frames, four steps, M4 24 GB:

denoise video VAE (no adapter anywhere near it)
base 126.1 s 53.4 s
+ fal Realism adapter 133.6 s 56.9 s

1.06Γ— on the denoise, and the VAE moved 6.5% between the same two runs β€” so on this machine an adapter costs at or below the run-to-run noise. My earlier 1.13Γ— and 1.37Γ— came from the base render itself drifting from 22.2 to 32.5 s a step under 6 GB of swap.

Where weights stream off disk, the adapter's extra work hides inside the streaming. Where the DiT is fully resident, the attention fusion it stands down should show up β€” that number is still owed, and I will post it when a card with headroom runs it.

Since this thread is where the Mac numbers live, the honest note for it: 0.5.96 does nothing for you.

It is a 10% win on a four-bit denoise (RTX 5090, 768Γ—448: 69.6 s β†’ 62.4 s, output byte-identical) and it is entirely on the wgpu/Vulkan path. Your M4 runs the Metal one.

What is worth carrying over from it is the diagnosis, because it was not where anyone was looking β€” including me. Profiling one fused FFN call on the four-bit path:

DiT shape 5376x14336, b=2447 : host 126.2 ms | card 41.4 ms
VAE shape 2048x8192,  b=1797 : host 100.2 ms | card 12.6 ms

Three quarters of the call was host work β€” buffer setup, bind groups, and a scan over the activation panel for max|x| on one core β€” before the GPU was asked for anything. On the pod's 27-core box that was still 10% of the render. On a laptop-class CPU sharing memory with the GPU it is likely worse, not better.

So the Metal side now has a specific thing to look for rather than "make the kernel faster", and I would rather tell you that than quietly ship a release note you cannot use.

Two more things from this evening that touch your machine directly:

  • The 24 GB frame budget. Chunked rendering (--stream-chunk 13, container mmh3-raven-streaming-q4tp.cmf) stops the activation cost growing with clip length. On the 5090 a 321-frame clip did not render at all bidirectionally β€” a single 2 GiB buffer binding β€” and took 354 s chunked. That limit is the same on your machine; the fix is in 0.5.95.
  • The eight-bit file (q8_2f) went from 171.5 s to 43 s at 512Γ—288 in 0.5.95. At 768Γ—448 it is now faster than the four-bit one (69 s against 131 s) with the more faithful codec. If you want the next quality step on the M1/64 GB, that is the file to try β€” though the same caveat applies, those numbers are the Vulkan path.

Correction to what I posted an hour ago, and this time with a Mac in front of me.

I said the host-preparation cost that dominates the Vulkan path was "likely worse, not better" on a laptop-class CPU sharing memory with the GPU. I have now measured it on an M4 with mmh3-turbo-clipproj4b-fl2va-v2-q4tp.cmf β€” 384Γ—256, 9 frames, four steps β€” and that guess was wrong:

q4tp mm x1091: upload 0.7 s Β· submit+wait 51.1 s Β· readback 1.3 s
stages: text encode 0.7s Β· denoise 52.1s Β· video vae 12.4s

Two seconds of host work out of 53. On Metal the copies are already nothing β€” unified memory does what it says β€” and effectively all of it is the kernel. The opposite of the Vulkan finding, and worth knowing before anyone spends a week porting today's fix to Metal: there is nothing there to win.

The harder number is what the kernel is doing. One four-step render at that size is about 210 TFLOP of arithmetic (50 blocks Γ— 1.05 TFLOP per block at ~1400 tokens). Against 51.1 s that is **4.1 TFLOPS sustained**, and the kernels already use Apple's simdgroup_matrix. An M4's GPU is in that neighbourhood. So the render is not waiting on bad code β€” it is doing the arithmetic the model asks for, at roughly the speed the machine can.

Which changes the advice I would give you for the 24 GB machine, and I would rather be useful than encouraging:

  1. Do less arithmetic, do not hope for a faster kernel. The levers that actually move it are the ones that shrink the token count: render small and --upscale (the latent upscaler decodes at the larger size without a second pass through the 5 B VAE), and --stream-chunk so the cost grows with the clip rather than with its square.
  2. The 45 minutes has a shape now. It is ~210 TFLOP per four-step pass at a small size, and it scales with tokens β€” double the frames, double the work, plus attention's own growth. That is why your frame budget feels like a cliff.
  3. The M1/64 GB is not faster per token, it is only bigger. Use it for the parts that need room (long clips, the VAE decode), not as a way to make one clip finish sooner.

I will keep the wgpu work where it belongs β€” it helps the NVIDIA users in #1 β€” and stop implying it will reach your machine.

Sign up or log in to comment