Files
Ethanfel 011c915fa7 release: ship H3 correctness fixes and research tools in 1.8.5
Publish the existing H3 merge/export and autotuner correctness fixes, offline character and AV calibration tools, provenance audits, and regression coverage. Add a dictionary-preserving storage hook for offline mapped TIES exports.

Keep scoring weights and defaults unchanged, retain NP/CT as opt-in, and exclude the rejected F08 search-admission prototype. Validate the exact staged tree: 1052 Python tests, 69 subtests, 3 JS tests, and real ComfyUI CPU export round trips pass; 3 CUDA-only tests skipped.
2026-09-09 12:10:02 +02:00

482 lines
26 KiB
Python

"""Isolated, paired before/after H3 search measurements; never installs nodes.
Fresh processes, identical source tensors/settings, explicit CUDA synchronization,
one warm-up per version/pair and three alternating-order measured repetitions.
Disconnected controls are separate. No render, remote API, learned judge, cache
release, automatic retry or overwrite. Worker RSS is bounded by a parent watchdog.
"""
import argparse
import hashlib
import importlib.util
import json
import math
import os
from pathlib import Path
import random
import resource
import statistics
import subprocess
import sys
import time
import types
try:
from .h3_benchmark import digest, save_new
from .h3_merge_study import PAIRS, header, check_gpu_headroom
from .h3_candidate_equivalence import require_idle
except ImportError:
from h3_benchmark import digest, save_new
from h3_merge_study import PAIRS, header, check_gpu_headroom
from h3_candidate_equivalence import require_idle
REPO = Path(__file__).resolve().parents[1]
# Privacy-safe published commit; identical tree to historical 27bedd7621e8e53b5d9c4d87ba594c2b7aa76008.
BASELINE = "cb92bd4f6e297fc16fe41889851801dcff792767"
BASELINE_SHA = "3d245ea08cda5aa4faf49cec9a878a93a521cb2bc71088d989f30c1d63346145"
PAIR_ORDER = ("series30_combat", "sully_cinema", "series30_cinema", "sully_combat")
SNAPSHOT_FILES = ("lora_optimizer.py", "experimental_merge.py", "kernel.py")
HELPERS = ("scripts/h3_search_benchmark.py", "scripts/h3_merge_study.py",
"scripts/h3_candidate_equivalence.py", "scripts/h3_benchmark.py", "scripts/h3_render_study.py")
ENV = dict(OMP_NUM_THREADS="4", MKL_NUM_THREADS="4", OPENBLAS_NUM_THREADS="4",
LORA_OPTIMIZER_PROFILE_MERGE="0", PYTHONHASHSEED="0")
SETTINGS = dict(top_n=3, normalize_keys="enabled", scoring_svd="disabled",
scoring_device="gpu", scoring_speed="full", memory_mode="disabled",
cache_patches="disabled", community_cache="disabled", diff_cache_mode="disabled",
record_dataset="disabled", output_mode="merge", vram_budget=.35)
def schedule():
jobs = []
for index, pair in enumerate(PAIR_ORDER):
for phase, repeats in (("disconnected", 1), ("warmup", 1), ("measured", 3)):
for repeat in range(repeats):
versions = ("baseline", "current") if (index + repeat) % 2 == 0 else ("current", "baseline")
for version in versions:
jobs.append(dict(id=f"{pair}-{phase}-{repeat}-{version}", pair=pair,
phase=phase, repeat=repeat, version=version))
return jobs
def prepare(out, comfy, loras):
if out.exists():
raise FileExistsError(out)
baseline = subprocess.check_output(["git", "show", f"{BASELINE}:lora_optimizer.py"], cwd=REPO)
if hashlib.sha256(baseline).hexdigest() != BASELINE_SHA:
raise ValueError("Unexpected committed baseline")
for name in ("experimental_merge.py", "kernel.py"):
old = subprocess.check_output(["git", "show", f"{BASELINE}:{name}"], cwd=REPO)
if old != (REPO / name).read_bytes():
raise ValueError("Baseline and current must use identical formula/kernel sources")
checkpoint = comfy / "models/diffusion_models/minimax_h3_fl2va_pruned_int8_convrot.safetensors"
shapes = header(checkpoint)
adapters = {}
for pair in PAIR_ORDER:
entries = []
for index, name in enumerate(PAIRS[pair]):
path = loras / (name + ".safetensors")
sidecar = json.loads(path.with_suffix(".metadata.json").read_text())
sha = digest(path)
if sha != sidecar["sha256"]:
raise ValueError("Adapter differs from recorded source identity")
entries.append(dict(path=str(path.resolve()), name=name + ".safetensors", sha256=sha,
strength=1. if index == 0 and pair.startswith("sully_") else .8))
adapters[pair] = entries
out.mkdir(parents=True)
snapshots = {}
for version in ("baseline", "current"):
directory = out / "sources" / version
directory.mkdir(parents=True)
files = {}
for name in SNAPSHOT_FILES:
payload = baseline if version == "baseline" and name == "lora_optimizer.py" else (REPO / name).read_bytes()
# Generated, isolated source artifacts, not a worktree checkout/edit.
with (directory / name).open("xb") as stream:
stream.write(payload)
files[name] = digest(directory / name)
snapshots[version] = dict(directory=str(directory.resolve()), files=files)
plan = dict(version=1, created_at=time.time(), baseline_commit=BASELINE,
root=str(out.resolve()), comfy=str(comfy.resolve()), loras=str(loras.resolve()),
queue_base="http://127.0.0.1:8189", snapshots=snapshots, adapters=adapters,
checkpoint=str(checkpoint.resolve()), checkpoint_size=checkpoint.stat().st_size,
checkpoint_header_sha256=hashlib.sha256(json.dumps(shapes, sort_keys=True).encode()).hexdigest(),
settings=SETTINGS, environment=ENV, merge_seed=2026090800, jobs=schedule(),
helper_sha256={name: digest(REPO / name) for name in HELPERS},
protocol=dict(warmups_per_pair_version=1, measured_repetitions=3,
experimental_trial_budget=dict(stable=3, additive_controls=1, np_lora=1, ct_merge=1),
timer="CUDA synchronize; perf_counter; actual auto_tune; CUDA synchronize",
timer_excludes="imports, source hashing/loading, context warm-up, winner hashing, serialization",
persistent_cache="new isolated models/user/temp directories per process; lookup/upload disabled",
winner_hash="raw stored model/CLIP patches, not a perceptual or base-model forward score",
concurrent_study_work="none during timed repetitions; no ffmpeg, tests or other GPU study",
limitations="GPU clocks are observed, not locked; system-wide CPU/I/O and queue activity are not continuously isolated. "
"Changing candidates changes useful work, so this is not a same-candidate microbenchmark."))
save_new(out / "plan.json", plan)
return plan
def validate_plan(path):
plan = json.loads(path.read_text())
if (plan.get("version") != 1 or plan.get("baseline_commit") != BASELINE
or plan.get("root") != str(path.parent.resolve())
or plan.get("queue_base") != "http://127.0.0.1:8189"
or plan.get("jobs") != schedule() or plan.get("settings") != SETTINGS
or plan.get("environment") != ENV or plan.get("merge_seed") != 2026090800
or set(plan["snapshots"]) != {"baseline", "current"}
or set(plan["helper_sha256"]) != set(HELPERS)
or set(plan["adapters"]) != set(PAIR_ORDER)):
raise ValueError("Benchmark scope/settings changed")
for name, sha in plan["helper_sha256"].items():
if digest(REPO / name) != sha:
raise ValueError("Benchmark helper changed")
for version, snapshot in plan["snapshots"].items():
if (Path(snapshot["directory"]) != path.parent.resolve() / "sources" / version
or set(snapshot["files"]) != set(SNAPSHOT_FILES)):
raise ValueError("Snapshot escaped scope")
for name, sha in snapshot["files"].items():
if digest(Path(snapshot["directory"]) / name) != sha:
raise ValueError("Snapshot changed")
if plan["snapshots"]["baseline"]["files"]["lora_optimizer.py"] != BASELINE_SHA:
raise ValueError("Baseline identity changed")
for name in ("experimental_merge.py", "kernel.py"):
if plan["snapshots"]["baseline"]["files"][name] != plan["snapshots"]["current"]["files"][name]:
raise ValueError("Formula/kernel difference confounds the comparison")
checkpoint = Path(plan["checkpoint"])
if (checkpoint.stat().st_size != plan["checkpoint_size"] or
hashlib.sha256(json.dumps(header(checkpoint), sort_keys=True).encode()).hexdigest() != plan["checkpoint_header_sha256"]):
raise ValueError("Shape-only base changed")
for pair, entries in plan["adapters"].items():
expected = [dict(name=name + ".safetensors", strength=1. if i == 0 and pair.startswith("sully_") else .8)
for i, name in enumerate(PAIRS[pair])]
if [{k: e[k] for k in ("name", "strength")} for e in entries] != expected:
raise ValueError("Source roles/strengths changed")
return plan
def hash_payload(value, *, chunk_elements=2 ** 20):
"""Deterministic typed digest including alpha, key offsets and signed zero."""
import torch
if chunk_elements <= 0:
raise ValueError("Positive hash chunk size required")
result = hashlib.sha256()
def visit(item):
if isinstance(item, torch.Tensor):
result.update(json.dumps(["tensor", str(item.dtype), list(item.shape)]).encode())
flat = item.detach().reshape(-1)
for start in range(0, flat.numel(), chunk_elements):
chunk = flat[start:start + chunk_elements].to("cpu").contiguous()
if not torch.isfinite(chunk).all().item():
raise ValueError("Non-finite winner payload")
result.update(chunk.view(torch.uint8).numpy().tobytes())
elif hasattr(item, "weights"):
result.update(type(item).__name__.encode())
visit(item.weights)
elif isinstance(item, dict):
result.update(b"dict")
for key in sorted(item, key=repr):
visit(key); visit(item[key])
result.update(b"end")
elif isinstance(item, (tuple, list)):
result.update(type(item).__name__.encode())
for part in item:
visit(part)
result.update(b"end")
elif item is None or isinstance(item, (str, int, float, bool)):
result.update(json.dumps([type(item).__name__, item], allow_nan=False).encode())
else:
raise ValueError(f"Unsupported winner payload: {type(item).__name__}")
visit(value)
return result.hexdigest()
def validate_candidate_budget(tuner, experimental):
rows = tuner["top_n"]
stable = [row for row in rows if "experimental" not in row["config"]
and not row["config"].get("experimental_baseline")]
controls = [row for row in rows if row["config"].get("experimental_baseline")]
methods = [row for row in rows if "experimental" in row["config"]]
if (tuner["analysis_summary"]["prefix_count"] != 312 or len(stable) != 3
or any(not math.isfinite(row["score_final"]) for row in rows)):
raise ValueError("Incomplete, non-finite or changed stable candidate budget")
if experimental is None:
if len(rows) != 3 or controls or methods:
raise ValueError("Disconnected path contains experimental trials")
elif (len(rows) != 6 or len(controls) != 1 or len(methods) != 2
or controls[0]["config"].get("experimental_baseline") is not True
or controls[0]["config"].get("merge_mode") != "weighted_sum"
or controls[0]["config"].get("optimization_mode") != "global"
or {row["config"]["merge_mode"] for row in methods} != {"np_lora", "ct_merge"}):
raise ValueError("Experimental budget must include additive control, NP and CT")
return dict(stable=len(stable), additive_controls=len(controls), experimental_methods=len(methods), total=len(rows))
def worker(plan_path, job_id):
plan = validate_plan(plan_path)
job = next(job for job in plan["jobs"] if job["id"] == job_id)
out = plan_path.parent / "runs" / job_id
out.mkdir(parents=True, exist_ok=False)
require_idle(plan["queue_base"])
for item in plan["adapters"][job["pair"]]:
if digest(item["path"]) != item["sha256"]:
raise ValueError("Actual adapter payload changed")
sys.path.insert(0, plan["comfy"])
sys.argv = [sys.argv[0], "--cpu"]
import comfy.options
comfy.options.enable_args_parsing()
import torch
import folder_paths
import comfy.lora
from comfy.model_patcher import ModelPatcher
from safetensors.torch import load_file
torch.set_num_threads(4)
torch.set_float32_matmul_precision("highest")
if not torch.cuda.is_available():
raise RuntimeError("Use the authorized GPU environment")
check_gpu_headroom("tune", torch.cuda.mem_get_info()[0])
folder_paths.set_user_directory(str(out / "user"))
folder_paths.set_temp_directory(str(out / "temp"))
folder_paths.models_dir = str(out / "models")
folder_paths.add_model_folder_path("loras", plan["loras"])
source = Path(plan["snapshots"][job["version"]]["directory"]) / "lora_optimizer.py"
spec = importlib.util.spec_from_file_location("h3_search_optimizer", source)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
module._LoRAMergeBase._get_compute_device = staticmethod(lambda: torch.device("cuda"))
import logging
logging.basicConfig(level=logging.INFO, force=True, handlers=[logging.FileHandler(out / "merge.log")])
class ShapeModel(torch.nn.Module):
def __init__(self):
super().__init__()
self.model_config = types.SimpleNamespace(unet_config={})
self.lora_optimizer_h3_profile = dict(partition="fl2va", basis="pruned")
for key, info in header(plan["checkpoint"]).items():
if key == "__metadata__" or not key.endswith((".weight", ".bias")):
continue
if info["dtype"] not in ("I8", "F16", "BF16", "F32"):
raise ValueError("Unsupported shape-only storage")
parent = self
parts = ("diffusion_model." + key).split(".")
for part in parts[:-1]:
if part not in parent._modules:
parent.add_module(part, torch.nn.Module())
parent = parent._modules[part]
parent.register_parameter(parts[-1], torch.nn.Parameter(
torch.empty(info["shape"], device="meta", dtype=torch.bfloat16), requires_grad=False))
model = ModelPatcher(ShapeModel(), torch.device("cpu"), torch.device("cpu"))
stack, native = [], []
mapping = comfy.lora.model_lora_keys_unet(model.model, {})
for item in plan["adapters"][job["pair"]]:
sd = load_file(item["path"])
if any("dora" in key.lower() or "adaln" in key.lower() for key in sd):
raise ValueError("Base-dependent source out of scope")
mapped = comfy.lora.load_lora(sd, mapping)
if set(sd) != set().union(*(p.loaded_keys for p in mapped.values())):
raise ValueError("Native source coverage incomplete")
native.append(set(mapped))
stack.append(dict(name=item["name"], lora=sd, strength=item["strength"],
metadata=header(item["path"]).get("__metadata__", {}), h3_layout="comfy"))
if len(set.union(*native)) != 208:
raise ValueError("Unexpected native target union")
del native, mapped, sd
# Equal lightweight CUDA initialization in every fresh process. No data from
# another trial or prior result enters the measured search.
init = torch.ones((256, 256), device="cuda")
init = init @ init
torch.cuda.synchronize()
del init
torch.cuda.empty_cache()
torch.manual_seed(plan["merge_seed"])
random.seed(plan["merge_seed"])
node = module.LoRAAutoTuner()
experimental = None if job["phase"] == "disconnected" else dict(np_lora=True, ct_merge=True)
torch.cuda.synchronize()
torch.cuda.reset_peak_memory_stats()
started = time.perf_counter()
output = node.auto_tune(model, stack, 1., **plan["settings"], experimental_options=experimental)
torch.cuda.synchronize()
elapsed = time.perf_counter() - started
peak = torch.cuda.max_memory_allocated()
peak_reserved = torch.cuda.max_memory_reserved()
tuner, data = output[4], output[5]
if data is None or len(data["model_patches"]) != 208 or data["clip_patches"]:
raise ValueError("Incomplete native winner output")
counts = validate_candidate_budget(tuner, experimental)
# Outside the measured interval: hash every raw winner patch, not sparse
# targets. This can detect changed output even when selected config agrees.
payload = hash_payload(dict(model=data["model_patches"], clip=data["clip_patches"]))
save_new(out / "tuner_data.json", tuner)
record = dict(job=job, plan_sha256=digest(plan_path), elapsed_seconds=elapsed,
peak_cuda_allocated=peak, peak_cuda_reserved=peak_reserved,
max_rss_bytes=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss * 1024,
winner_payload_sha256=payload, winner_native_targets=208,
candidate_counts=counts,
tuner_sha256=digest(out / "tuner_data.json"), log_sha256=digest(out / "merge.log"),
torch_version=torch.__version__, cuda_device=torch.cuda.get_device_name(0),
cuda_matmul_allow_tf32=torch.backends.cuda.matmul.allow_tf32,
matmul_precision=torch.get_float32_matmul_precision(),
svd_kernel_loaded=module._HAS_SVD_KERNEL, triton_available=module._HAS_TRITON,
triton_disabled=module._DISABLE_TRITON,
actual_experimental_options=tuner.get("experimental_options"),
snapshots=plan["snapshots"][job["version"]]["files"])
save_new(out / "result.json", record)
del output, model, node, stack, data
def measured_summary(records):
if [r["job"] for r in records] != schedule():
raise ValueError("All predeclared trials are required, including controls/warm-ups")
pairs = {}
for pair in PAIR_ORDER:
stats = {}
for version in ("baseline", "current"):
selected = [r for r in records if r["job"]["pair"] == pair and r["job"]["version"] == version
and r["job"]["phase"] == "measured"]
times = [r["elapsed_seconds"] for r in selected]
if len(times) != 3 or any(not math.isfinite(t) or t <= 0 for t in times):
raise ValueError("Invalid or incomplete synchronized timing")
stats[version] = dict(seconds=times, median_seconds=statistics.median(times),
peak_cuda_bytes=[r["peak_cuda_allocated"] for r in selected],
winner_payload_sha256=[r["winner_payload_sha256"] for r in selected])
stats["current_over_baseline_median_time"] = stats["current"]["median_seconds"] / stats["baseline"]["median_seconds"]
pairs[pair] = stats
return pairs
def candidate_identity(row):
return json.dumps(row["config"], sort_keys=True, allow_nan=False)
def compare_searches(records, root):
"""Keep default regressions, changed admission, scores and payloads separate."""
tuners = {}
for record in records:
path = root / "runs" / record["job"]["id"] / "tuner_data.json"
if digest(path) != record["tuner_sha256"]:
raise ValueError("Tuner record changed")
tuners[record["job"]["id"]] = json.loads(path.read_text())
comparisons = {}
for pair in PAIR_ORDER:
controls = {r["job"]["version"]: r for r in records if r["job"]["pair"] == pair
and r["job"]["phase"] == "disconnected"}
a, b = [tuners[controls[v]["job"]["id"]] for v in ("baseline", "current")]
def rows_equal(a, b):
return (len(a) == len(b) and all(candidate_identity(x) == candidate_identity(y)
and x.get("per_prefix_decisions") == y.get("per_prefix_decisions")
and math.isclose(x["score_final"], y["score_final"], rel_tol=1e-9, abs_tol=1e-9)
for x, y in zip(a, b)))
control_equal = (rows_equal(a["top_n"], b["top_n"])
and controls["baseline"]["winner_payload_sha256"] == controls["current"]["winner_payload_sha256"])
runs = []
for repeat in range(3):
selected = {r["job"]["version"]: r for r in records if r["job"]["pair"] == pair
and r["job"]["phase"] == "measured" and r["job"]["repeat"] == repeat}
baseline, current = [tuners[selected[v]["job"]["id"]] for v in ("baseline", "current")]
old, new = [{candidate_identity(row): row for row in t["top_n"]} for t in (baseline, current)]
common = sorted(old.keys() & new.keys())
runs.append(dict(repeat=repeat, admitted=[new[k]["config"] for k in sorted(new.keys()-old.keys())],
removed=[old[k]["config"] for k in sorted(old.keys()-new.keys())],
baseline_winner=baseline["top_n"][0]["config"], current_winner=current["top_n"][0]["config"],
winner_payload_equal=selected["baseline"]["winner_payload_sha256"] == selected["current"]["winner_payload_sha256"],
common_candidate_score_changes=[dict(config=old[k]["config"],
current_minus_baseline=new[k]["score_final"]-old[k]["score_final"],
per_prefix_decisions_equal=new[k].get("per_prefix_decisions") == old[k].get("per_prefix_decisions")) for k in common],
current_dedup=current.get("experimental_dedup")))
comparisons[pair] = dict(disconnected_configs_scores_and_payload_equal=control_equal, measured=runs)
return comparisons
def gpu_telemetry():
fields = "index,name,driver_version,memory.free,utilization.gpu,temperature.gpu,clocks.current.sm,clocks.current.memory,power.draw"
return dict(fields=fields.split(","), csv=subprocess.check_output(
["nvidia-smi", "--query-gpu=" + fields, "--format=csv,noheader,nounits"], text=True).strip())
def run(plan_path):
import psutil
plan = validate_plan(plan_path)
root = plan_path.parent
if (root / "runs").exists() or (root / "summary.json").exists():
raise FileExistsError("Existing/partial execution; inspect it instead of restarting")
(root / "runs").mkdir()
records = []
env = {**os.environ, **plan["environment"]}
for job in plan["jobs"]:
require_idle(plan["queue_base"])
# A conservative guard for our owned worker, never unrelated processes.
rss_limit = min(26 * 1024 ** 3, int(psutil.virtual_memory().available * .70))
if rss_limit < 12 * 1024 ** 3:
raise RuntimeError("Insufficient free RAM for a controlled H3 sweep")
before = dict(gpu=gpu_telemetry(), available_ram=psutil.virtual_memory().available,
time=time.time())
print(json.dumps({"starting": job, "rss_limit_bytes": rss_limit}), flush=True)
command = [sys.executable, str(Path(__file__).resolve()), "worker", "--plan", str(plan_path.resolve()), "--job", job["id"]]
with (root / "runs" / (job["id"] + ".log")).open("x") as log:
child = subprocess.Popen(command, env=env, stdout=log, stderr=subprocess.STDOUT)
memory_exceeded = False
while child.poll() is None:
try:
process = psutil.Process(child.pid)
rss = process.memory_info().rss + sum(p.memory_info().rss for p in process.children(recursive=True))
if rss > rss_limit:
memory_exceeded = True
child.terminate()
try:
child.wait(timeout=15)
except subprocess.TimeoutExpired:
child.kill()
child.wait()
break
except psutil.NoSuchProcess:
pass
time.sleep(.5)
returncode = child.wait()
if returncode or memory_exceeded:
save_new(root / "stopped.json", dict(job=job, returncode=returncode, rss_limit_bytes=rss_limit,
memory_exceeded=memory_exceeded, automatic_retry=False))
raise RuntimeError(f"Owned benchmark worker failed: {job['id']}; inspect its log, no retry")
require_idle(plan["queue_base"])
result_path = root / "runs" / job["id"] / "result.json"
result = json.loads(result_path.read_text())
if result["plan_sha256"] != digest(plan_path) or result["job"] != job:
raise ValueError("Worker receipt does not match the scheduled trial")
telemetry = dict(before=before, after=dict(gpu=gpu_telemetry(), available_ram=psutil.virtual_memory().available,
time=time.time()), worker_rss_limit_bytes=rss_limit)
save_new(result_path.parent / "telemetry.json", telemetry)
result["telemetry_sha256"] = digest(result_path.parent / "telemetry.json")
records.append(result)
print(json.dumps({"completed": job["id"], "seconds": result["elapsed_seconds"],
"peak_cuda_bytes": result["peak_cuda_allocated"]}), flush=True)
summary = dict(plan_sha256=digest(plan_path), records=records, pairs=measured_summary(records),
comparisons=compare_searches(records, root),
quality_claim=False, note=plan["protocol"]["limitations"])
save_new(root / "summary.json", summary)
print(json.dumps({"completed_trials": len(records), "summary": str(root / "summary.json")}), flush=True)
def main():
parser = argparse.ArgumentParser(description=__doc__)
sub = parser.add_subparsers(dest="action", required=True)
prep = sub.add_parser("prepare")
prep.add_argument("--out", type=Path, required=True)
prep.add_argument("--comfy", type=Path, default=Path("/media/p5/Comfyui"))
prep.add_argument("--loras", type=Path, default=Path("/media/p5/ComfyUI-Model-CIFS-Cache/loras/MiniMax H3"))
execute = sub.add_parser("run")
execute.add_argument("--plan", type=Path, required=True)
work = sub.add_parser("worker")
work.add_argument("--plan", type=Path, required=True)
work.add_argument("--job", required=True)
args = parser.parse_args()
if args.action == "prepare":
plan = prepare(args.out, args.comfy, args.loras)
print(json.dumps({"trials": len(plan["jobs"]), "plan": str(args.out / "plan.json")}))
elif args.action == "run":
run(args.plan)
else:
worker(args.plan, args.job)
if __name__ == "__main__":
main()