Files
Archerkattri-ComfyUI-HiCache/nodes.py
T
Krishi Attri ebe139e5f5 v0.2.0: GPU-validated inside ComfyUI; copy-on-patch cache safety; single-step reset fix
End-to-end validation on RTX 5090 (ComfyUI 0.24.0, Hunyuan3DWrapper master,
Hunyuan3D-2mini fp16, 30-step image-to-mesh workflow via the ComfyUI API):

- patch engages exactly on schedule (hermite i3: 11 computed + 19 skipped;
  dmd i5: 7 + 23), sampling 16.1 -> 43.1 it/s (2.68x) for hermite i3
- quality A/B same seed vs unaccelerated mesh: hermite i3 F1@0.05 0.825
  (different-seed floor 0.751); dmd i5 0.719, at the floor on mini, so the
  upstream DMD lossless claim is not repeated for this node
- repeat runs in one session reset per-run state correctly

Two bugs found by the validation, both fixed with regression tests:

1. ComfyUI cache aliasing: the node mutated and returned the same pipeline
   object, so a cached node output could silently run a different config
   after an intervening run re-patched the shared pipeline (observed live:
   a cached hermite-i3 output ran dmd-i5). apply/remove now return a
   shallow copy that owns its patch; the input pipeline is never mutated.
2. Run-boundary reset missed back-to-back single-step runs (t=0 then t=0);
   the boundary check is now non-increasing instead of strictly decreasing.

Defaults switch to the best-measured config (hermite, interval 3).
Tests 35 -> 38. README validation section rewritten from measurements;
REGISTRY-SUBMIT.md documents the registry.comfy.org publish flow.
2026-06-11 01:42:19 +00:00

105 lines
4.5 KiB
Python

"""ComfyUI-HiCache node definitions.
One node, no ComfyUI-internal imports: the patch operates directly on the
pipeline object that kijai/ComfyUI-Hunyuan3DWrapper passes between nodes as
the custom ``HY3DMODEL`` type, so this file imports cleanly outside ComfyUI
too (which is how the unit tests run it).
"""
from __future__ import annotations
try:
from .hicache_patch import METHODS, apply_hicache, remove_hicache
except ImportError: # imported outside ComfyUI (tests / tooling), not as a package
from hicache_patch import METHODS, apply_hicache, remove_hicache
class HiCacheAccelerate:
"""Training-free Hunyuan3D shape-DiT acceleration via velocity forecasting.
Wire between the Hunyuan3DWrapper model loader (``Hy3DModelLoader``) and
the mesh sampler (``Hy3DGenerateMesh`` / ``Hy3DGenerateMeshMultiView``).
On skipped sampling steps the DiT forward is replaced by a cheap forecast
from cached velocities (HiCache Hermite / HiCache++ DMD), cutting the
diffusion-sampling wall clock by roughly ``(interval-1)/interval`` of the
DiT time.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"pipeline": ("HY3DMODEL", {
"tooltip": "Hunyuan3D shape pipeline from Hy3DModelLoader "
"(kijai/ComfyUI-Hunyuan3DWrapper)."}),
"method": (list(METHODS), {
"default": "hermite",
"tooltip": "Forecast basis on skipped steps:\n"
"hermite = HiCache (polynomial, arXiv:2508.16984; "
"best measured quality inside ComfyUI)\n"
"dmd = HiCache++ (exponential / Prony-DMD; worth "
"trying at large intervals on the big 2.1 DiT)\n"
"auto = holdout-pick the better of the two per "
"compute step"}),
"interval": ("INT", {
"default": 3, "min": 1, "max": 12, "step": 1,
"tooltip": "Compute one DiT step, then forecast interval-1 "
"steps. 1 = caching disabled (every step computed). "
"Measured sweet spot inside ComfyUI: hermite "
"interval 3."}),
"warmup_steps": ("INT", {
"default": 2, "min": 0, "max": 100, "step": 1,
"tooltip": "Always compute the first N sampling steps before "
"any forecasting starts."}),
},
"optional": {
"enable": ("BOOLEAN", {
"default": True,
"tooltip": "Off = remove the patch and restore the original "
"DiT forward."}),
"max_order": ("INT", {
"default": 1, "min": 1, "max": 4, "step": 1,
"tooltip": "Highest Hermite / finite-difference order "
"(hermite method and warm-up fallback)."}),
"sigma": ("FLOAT", {
"default": 0.5, "min": 0.05, "max": 0.95, "step": 0.05,
"tooltip": "Hermite contraction factor in (0,1); keeps "
"high-order terms bounded."}),
"dmd_history": ("INT", {
"default": 5, "min": 3, "max": 16, "step": 1,
"tooltip": "DMD snapshot window length (dmd/auto methods)."}),
},
}
RETURN_TYPES = ("HY3DMODEL",)
RETURN_NAMES = ("pipeline",)
FUNCTION = "patch"
CATEGORY = "HiCache"
DESCRIPTION = (
"Training-free acceleration of Hunyuan3D shape generation: skip DiT "
"forwards and forecast the flow-matching velocity instead (HiCache "
"Hermite / HiCache++ DMD, via the hicache-pp library)."
)
def patch(self, pipeline, method="hermite", interval=3, warmup_steps=2,
enable=True, max_order=1, sigma=0.5, dmd_history=5):
if not enable or interval <= 1:
return (remove_hicache(pipeline),)
return (apply_hicache(
pipeline,
method=method,
interval=interval,
warmup_steps=warmup_steps,
max_order=max_order,
sigma=sigma,
dmd_history=dmd_history,
),)
NODE_CLASS_MAPPINGS = {
"HiCacheAccelerate": HiCacheAccelerate,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"HiCacheAccelerate": "HiCache Accelerate (Hunyuan3D)",
}