unsloth/studio/backend/tests/test_sd_cpp_engine.py
Daniel Han 395816cf7e Studio diffusion (Phase 7): accuracy-preserving speed pass
Re-review of the diffusion stack (#6675/#6679/#6680) surfaced one real accuracy
bug and a dead-on-arrival speed path; this fixes both and adds the lossless /
near-lossless wins, all measured on a B200.

Correctness:
- TF32 global-state leak (fix). speed_mode=max flipped torch.backends.*.allow_tf32
  process-wide and never restored them, so a later `off` load silently inherited
  TF32 and was no longer bit-identical. Added snapshot_backend_flags /
  restore_backend_flags (TF32 + cudnn.benchmark), captured before the speed layer
  runs and restored on unload. Verified: load max -> unload -> load off is now
  byte-identical (PSNR inf) to a fresh off.
- sd-cli timeout could hang forever. _run() blocked in `for line in stdout` and
  only checked the timeout after EOF, so a child stuck in model load / GPU init
  with no output ignored the timeout. Drained stdout on a reader thread with a
  wall-clock deadline. Added a silent-hang regression test.

Speed (diffusers path), near-lossless, opt-in tiers:
- Regional torch.compile now runs on the GGUF transformer. The is_gguf gate (and
  Z-Image's supports_torch_compile=False) were stale: compile_repeated_blocks
  compiles and runs ~2.2x faster on the GGUF Z-Image transformer on
  torch 2.9.1 / diffusers 0.38 (the per-op dequant stays eager, the rest of the
  block compiles). Measured: off 1.80s -> default 0.82s/gen (+54.7%), PSNR 37.7 dB
  vs eager -- far above the Q4 quant noise floor (~21 dB), so it does not move
  output quality. Gate relaxed; default tier delivers it.
- cudnn.benchmark added to the default tier (autotunes the fixed-shape VAE convs).
- torch.inference_mode() around the pipeline call (lossless, strictly faster than
  the no_grad diffusers uses internally).

Memory path:
- VAE tiling (not bit-identical >1MP) restricted to the model/sequential/CPU tiers;
  the balanced (group) tier keeps exact slicing only, so it is now bit-identical to
  the resident image (verified PSNR inf) and slightly faster.
- Group offload adds non_blocking + record_stream on the CUDA stream path to
  overlap each block's H2D copy with compute (lossless; gated on the installed
  diffusers signature so older versions still work).

Native (sd.cpp) path:
- native_speed_flags: a first-class speed knob (default -> --diffusion-fa, a
  near-lossless CUDA win that was previously only added on offload tiers; max also
  -> --diffusion-conv-direct). conv-direct stays opt-in: measured +45% on CUDA, so
  it is never auto-on. Engine generate() merges it, de-duped against offload flags.

Default profile: a GGUF model with no explicit speed_mode now resolves to the
`default` profile (resolve_speed_mode), since compile's perturbation sits below the
quantisation noise floor and so does not reduce quality versus the dense reference;
out of the box a GGUF Z-Image generation drops from 1.80s to 0.81s. Dense models
stay `off` / bit-identical, and an explicit speed_mode -- including "off" -- is
always honored, so the byte-identical path remains one flag away and is the
regression reference.

Tooling: scripts/compile_probe.py (eager vs compiled GGUF probe), scripts/
perf_verify.py (the B200 verification above), and diffusion_bench.py gains
--speed-mode so the speed tiers are benchmarkable.

Tests: 183 passing (was 166); new coverage for the backend-flag snapshot/restore,
GGUF compile eligibility, the balanced tiling/slicing split, native_speed_flags +
the engine de-dup, and the sd-cli silent-hang timeout.
2026-06-26 03:18:44 +00:00

387 lines
13 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
"""Unit tests for the sd-cli engine + routing (``sd_cpp_engine.py``).
Hermetic: the binary finder is driven against a tmp filesystem, and ``generate``
runs a fake ``subprocess.Popen`` that emits canned lines and writes the output
PNG -- no real ``sd-cli``, no GPU.
"""
from __future__ import annotations
import os
import sys
import time
import types
from pathlib import Path
import pytest
from core.inference import sd_cpp_engine as eng
from core.inference.sd_cpp_engine import (
ENGINE_DIFFUSERS,
ENGINE_SD_CPP,
SdCppEngine,
find_sd_cpp_binary,
runtime_env,
select_diffusion_engine,
)
from core.inference.sd_cpp_args import SdCppGenParams, SdCppModelFiles, SdCppUpscaleParams
# ── binary discovery ────────────────────────────────────────────────────────
def _clear_env(monkeypatch):
monkeypatch.delenv("SD_CLI_PATH", raising = False)
monkeypatch.delenv("UNSLOTH_SD_CPP_PATH", raising = False)
def test_find_prefers_sd_cli_path_env(tmp_path, monkeypatch):
_clear_env(monkeypatch)
binary = tmp_path / "sd-cli"
binary.write_text("#!/bin/sh\n")
monkeypatch.setenv("SD_CLI_PATH", str(binary))
# even with PATH empty, the direct env wins
monkeypatch.setattr(eng.shutil, "which", lambda *_a: None)
assert find_sd_cpp_binary() == str(binary)
def test_find_custom_install_dir_build_layout(tmp_path, monkeypatch):
_clear_env(monkeypatch)
root = tmp_path / "sdcpp"
built = root / "build" / "bin" / "sd-cli"
built.parent.mkdir(parents = True)
built.write_text("x")
monkeypatch.setenv("UNSLOTH_SD_CPP_PATH", str(root))
monkeypatch.setattr(eng.shutil, "which", lambda *_a: None)
assert find_sd_cpp_binary() == str(built)
def test_find_falls_back_to_path(tmp_path, monkeypatch):
_clear_env(monkeypatch)
monkeypatch.setattr(eng.Path, "home", staticmethod(lambda: tmp_path / "nohome"))
monkeypatch.setattr(
eng.shutil, "which", lambda stem: "/usr/bin/sd-cli" if stem == "sd-cli" else None
)
assert find_sd_cpp_binary() == "/usr/bin/sd-cli"
def test_find_returns_none_when_absent(tmp_path, monkeypatch):
_clear_env(monkeypatch)
monkeypatch.setattr(eng.Path, "home", staticmethod(lambda: tmp_path / "nohome"))
monkeypatch.setattr(eng.shutil, "which", lambda *_a: None)
assert find_sd_cpp_binary() is None
# ── availability / version ──────────────────────────────────────────────────
def test_engine_unavailable_when_no_binary():
e = SdCppEngine(binary = None)
assert e.is_available() is False
assert e.version() is None
def test_engine_version_parsed_and_cached(tmp_path, monkeypatch):
binary = tmp_path / "sd-cli"
binary.write_text("x")
e = SdCppEngine(binary = str(binary))
calls = {"n": 0}
def _fake_run(*_a, **_k):
calls["n"] += 1
return types.SimpleNamespace(stdout = "stable-diffusion.cpp version master-721\n", stderr = "")
monkeypatch.setattr(eng.subprocess, "run", _fake_run)
assert e.version() == "stable-diffusion.cpp version master-721"
assert e.version() == "stable-diffusion.cpp version master-721"
assert calls["n"] == 1 # cached after the first probe
# ── runtime env (bundled shared libs) ───────────────────────────────────────
def test_runtime_env_prepends_binary_dir_to_lib_path():
var = eng._lib_path_var()
env = runtime_env("/opt/sdcpp/bin/sd-cli", {var: "/existing"})
first = env[var].split(os.pathsep)[0]
assert first == "/opt/sdcpp/bin"
assert "/existing" in env[var]
def test_runtime_env_handles_missing_lib_path():
var = eng._lib_path_var()
env = runtime_env("/opt/sdcpp/bin/sd-cli", {})
assert env[var] == "/opt/sdcpp/bin"
# ── generate (fake subprocess) ──────────────────────────────────────────────
class _FakePopen:
"""Stand-in for subprocess.Popen: streams ``lines`` then writes ``out_file``
(unless ``write`` is False) and exits with ``returncode``."""
captured_cmd: list[str] = []
captured_env: dict = {}
def __init__(
self,
cmd,
*,
lines,
returncode,
out_file,
write,
env = None,
):
type(self).captured_cmd = list(cmd)
type(self).captured_env = dict(env or {})
self._lines = list(lines)
self.returncode = returncode
self._out_file = out_file
self._write = write
@property
def stdout(self):
return iter(self._lines)
def wait(self, timeout = None):
if self._write:
Path(self._out_file).write_bytes(b"\x89PNG\r\n")
return self.returncode
def poll(self):
return self.returncode
def kill(self):
pass
def _patch_popen(
monkeypatch,
*,
lines,
returncode,
out_file,
write = True,
):
def _factory(cmd, **kw):
return _FakePopen(
cmd,
lines = lines,
returncode = returncode,
out_file = out_file,
write = write,
env = kw.get("env"),
)
monkeypatch.setattr(eng.subprocess, "Popen", _factory)
def _engine(tmp_path):
binary = tmp_path / "sd-cli"
binary.write_text("x")
return SdCppEngine(binary = str(binary))
def test_generate_success_returns_path_and_collects_logs(tmp_path, monkeypatch):
e = _engine(tmp_path)
out = tmp_path / "img.png"
_patch_popen(
monkeypatch, lines = ["loading model", "step 1/8", "done"], returncode = 0, out_file = out
)
seen: list[str] = []
files = SdCppModelFiles(diffusion_model = "/m/z.gguf", vae = "/m/ae.sft", llm = "/m/q.gguf")
params = SdCppGenParams(prompt = "a cat", steps = 8, seed = 1)
result = e.generate(files, params, output_path = str(out), on_log = seen.append)
assert result == out and out.is_file()
assert seen == ["loading model", "step 1/8", "done"]
# the real argv was built and handed to Popen
assert "--diffusion-model" in _FakePopen.captured_cmd
assert str(out) == _FakePopen.captured_cmd[_FakePopen.captured_cmd.index("--output") + 1]
# the subprocess env carries the binary's dir on the library path
var = eng._lib_path_var()
assert str(Path(e.binary).resolve().parent) in _FakePopen.captured_env.get(var, "")
def test_generate_raises_on_nonzero_exit(tmp_path, monkeypatch):
e = _engine(tmp_path)
out = tmp_path / "img.png"
_patch_popen(monkeypatch, lines = ["boom: bad gguf"], returncode = 1, out_file = out, write = False)
with pytest.raises(RuntimeError, match = "exited 1"):
e.generate(
SdCppModelFiles(diffusion_model = "/m/z.gguf"),
SdCppGenParams(prompt = "x"),
output_path = str(out),
)
def test_generate_raises_when_no_output_despite_success(tmp_path, monkeypatch):
e = _engine(tmp_path)
out = tmp_path / "img.png"
_patch_popen(monkeypatch, lines = ["ok"], returncode = 0, out_file = out, write = False)
with pytest.raises(RuntimeError, match = "no image"):
e.generate(
SdCppModelFiles(diffusion_model = "/m/z.gguf"),
SdCppGenParams(prompt = "x"),
output_path = str(out),
)
def test_generate_raises_when_binary_missing():
e = SdCppEngine(binary = None)
with pytest.raises(RuntimeError, match = "not found"):
e.generate(
SdCppModelFiles(diffusion_model = "/m/z.gguf"),
SdCppGenParams(prompt = "x"),
output_path = "/tmp/x.png",
)
class _HangingPopen:
"""A child that runs but never prints and never exits -- the case a plain
`for line in stdout` would block on forever, ignoring the timeout."""
def __init__(self, cmd, **_kw):
self._alive = True
class _Blocking:
def __init__(self, owner):
self.owner = owner
def __iter__(self):
return self
def __next__(self):
while self.owner._alive:
time.sleep(0.01)
raise StopIteration
@property
def stdout(self):
return self._Blocking(self)
def poll(self):
return None if self._alive else -9
def wait(self, timeout = None):
self._alive = False
return -9
def kill(self):
self._alive = False
def test_generate_times_out_on_silent_hang(tmp_path, monkeypatch):
e = _engine(tmp_path)
monkeypatch.setattr(eng.subprocess, "Popen", lambda cmd, **kw: _HangingPopen(cmd, **kw))
t0 = time.time()
with pytest.raises(RuntimeError, match = "timed out"):
e.generate(
SdCppModelFiles(diffusion_model = "/m/z.gguf"),
SdCppGenParams(prompt = "x"),
output_path = str(tmp_path / "x.png"),
timeout = 0.3,
)
# The timeout is enforced promptly (not blocked until stdout EOF).
assert time.time() - t0 < 5.0
def test_img2img_generate_passes_init_image(tmp_path, monkeypatch):
e = _engine(tmp_path)
out = tmp_path / "img.png"
src = tmp_path / "src.png"
src.write_bytes(b"\x89PNG\r\n")
_patch_popen(monkeypatch, lines = ["img2img"], returncode = 0, out_file = out)
e.generate(
SdCppModelFiles(diffusion_model = "/m/z.gguf"),
SdCppGenParams(prompt = "x", init_img = str(src), strength = 0.5),
output_path = str(out),
)
assert "--init-img" in _FakePopen.captured_cmd
assert str(src) == _FakePopen.captured_cmd[_FakePopen.captured_cmd.index("--init-img") + 1]
def test_generate_native_speed_dedupes_against_offload(tmp_path, monkeypatch):
e = _engine(tmp_path)
out = tmp_path / "img.png"
_patch_popen(monkeypatch, lines = ["ok"], returncode = 0, out_file = out)
# offload already adds --diffusion-fa; native_speed="default" would add it again.
e.generate(
SdCppModelFiles(diffusion_model = "/m/z.gguf"),
SdCppGenParams(prompt = "x"),
output_path = str(out),
offload = ["--offload-to-cpu", "--diffusion-fa"],
native_speed = "default",
)
# --diffusion-fa appears exactly once (de-duped), not twice.
assert _FakePopen.captured_cmd.count("--diffusion-fa") == 1
def test_generate_native_speed_adds_flag_when_not_offloaded(tmp_path, monkeypatch):
e = _engine(tmp_path)
out = tmp_path / "img.png"
_patch_popen(monkeypatch, lines = ["ok"], returncode = 0, out_file = out)
e.generate(
SdCppModelFiles(diffusion_model = "/m/z.gguf"),
SdCppGenParams(prompt = "x"),
output_path = str(out),
offload = [], # fast/resident tier: no offload, but speed flag still applies
native_speed = "default",
)
assert _FakePopen.captured_cmd.count("--diffusion-fa") == 1
def test_upscale_runs_and_returns_path(tmp_path, monkeypatch):
e = _engine(tmp_path)
out = tmp_path / "big.png"
_patch_popen(monkeypatch, lines = ["upscaling", "done"], returncode = 0, out_file = out)
result = e.upscale(
SdCppUpscaleParams(input_image = "/in/small.png", upscale_model = "/m/esrgan.pth", repeats = 2),
output_path = str(out),
)
assert result == out and out.is_file()
assert _FakePopen.captured_cmd[_FakePopen.captured_cmd.index("--mode") + 1] == "upscale"
assert "--upscale-model" in _FakePopen.captured_cmd
def test_upscale_raises_when_binary_missing():
e = SdCppEngine(binary = None)
with pytest.raises(RuntimeError, match = "not found"):
e.upscale(
SdCppUpscaleParams(input_image = "/i.png", upscale_model = "/m/e.pth"),
output_path = "/tmp/x.png",
)
# ── engine routing ──────────────────────────────────────────────────────────
def test_routing_gpu_backends_use_diffusers():
for backend in ("cuda", "rocm", "xpu"):
assert select_diffusion_engine(backend, native_available = True) == ENGINE_DIFFUSERS
def test_routing_cpu_and_mps_use_native_when_available():
assert select_diffusion_engine("cpu", native_available = True) == ENGINE_SD_CPP
assert select_diffusion_engine("mps", native_available = True) == ENGINE_SD_CPP
def test_routing_cpu_falls_back_to_diffusers_without_binary():
assert select_diffusion_engine("cpu", native_available = False) == ENGINE_DIFFUSERS
def test_routing_prefer_native_overrides_gpu():
assert (
select_diffusion_engine("cuda", native_available = True, prefer_native = True) == ENGINE_SD_CPP
)
# but only if a binary is actually available
assert (
select_diffusion_engine("cuda", native_available = False, prefer_native = True)
== ENGINE_DIFFUSERS
)