mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-07-20 13:28:19 +08:00
fix: address CodeRabbit feedback — QuaRot error surface, LoRA shape validation, Sylvester bug fix, cache cap
This commit is contained in:
parent
b5d471f5ff
commit
3e5738da24
@ -74,18 +74,15 @@ class TINT4Linear(nn.Module):
|
|||||||
|
|
||||||
# ── QuaRot activation rotation (online) ──────────────────
|
# ── QuaRot activation rotation (online) ──────────────────
|
||||||
if self._use_quarot and self._hadamard_H is not None:
|
if self._use_quarot and self._hadamard_H is not None:
|
||||||
try:
|
if x_flat.shape[-1] % self._group_size != 0:
|
||||||
H_dev = self._hadamard_H.to(
|
raise ValueError(
|
||||||
device=x.device,
|
f"activation dim {x_flat.shape[-1]} not divisible "
|
||||||
dtype=(x.dtype if x.dtype in (
|
f"by QuaRot group_size {self._group_size}"
|
||||||
torch.float16, torch.bfloat16)
|
|
||||||
else torch.float16),
|
|
||||||
)
|
)
|
||||||
n_groups = x_flat.shape[-1] // self._group_size
|
H_dev = self._hadamard_H.to(device=x.device, dtype=x.dtype)
|
||||||
x_g = x_flat.view(-1, n_groups, self._group_size)
|
n_groups = x_flat.shape[-1] // self._group_size
|
||||||
x_flat = torch.matmul(x_g, H_dev).view(-1, x_g.shape[2] * n_groups)
|
x_g = x_flat.view(-1, n_groups, self._group_size)
|
||||||
except Exception:
|
x_flat = torch.matmul(x_g, H_dev).view(-1, n_groups * self._group_size)
|
||||||
pass
|
|
||||||
|
|
||||||
dev = x.device
|
dev = x.device
|
||||||
|
|
||||||
@ -105,6 +102,7 @@ class TINT4Linear(nn.Module):
|
|||||||
else torch.float16)
|
else torch.float16)
|
||||||
for lora_entries in entries.values():
|
for lora_entries in entries.values():
|
||||||
for e in lora_entries:
|
for e in lora_entries:
|
||||||
|
# ── LoKr path ────────────────────────────────
|
||||||
if isinstance(e[0], str) and e[0] == "lokr":
|
if isinstance(e[0], str) and e[0] == "lokr":
|
||||||
_, w1, w2, mult, factor = e[:5]
|
_, w1, w2, mult, factor = e[:5]
|
||||||
sl = e[5] if len(e) > 5 else None
|
sl = e[5] if len(e) > 5 else None
|
||||||
@ -118,13 +116,23 @@ class TINT4Linear(nn.Module):
|
|||||||
dw = (w1x * w2d).mul_(mult)
|
dw = (w1x * w2d).mul_(mult)
|
||||||
lo = x_flat.to(cd) @ dw.T
|
lo = x_flat.to(cd) @ dw.T
|
||||||
if sl is not None:
|
if sl is not None:
|
||||||
if lo.shape[1] == (se - sl):
|
if lo.shape[1] != (se - sl):
|
||||||
out[:, sl:se] += lo
|
raise ValueError(
|
||||||
|
f"LoKr output width {lo.shape[1]} "
|
||||||
|
f"doesn't match target slice width "
|
||||||
|
f"{se - sl}"
|
||||||
|
)
|
||||||
|
out[:, sl:se] += lo
|
||||||
elif lo.shape == out.shape:
|
elif lo.shape == out.shape:
|
||||||
out += lo
|
out += lo
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"LoKr output shape {lo.shape} "
|
||||||
|
f"incompatible with {out.shape}"
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# standard LoRA
|
# ── Standard LoRA path ────────────────────────
|
||||||
A, B, mult = e[:3]
|
A, B, mult = e[:3]
|
||||||
sl = e[3] if len(e) > 3 else None
|
sl = e[3] if len(e) > 3 else None
|
||||||
se = e[4] if len(e) > 4 else None
|
se = e[4] if len(e) > 4 else None
|
||||||
@ -132,10 +140,20 @@ class TINT4Linear(nn.Module):
|
|||||||
Bd = B.to(device=dev, dtype=cd)
|
Bd = B.to(device=dev, dtype=cd)
|
||||||
lo = (x_flat.to(cd) @ Ad.T) @ Bd.T * mult
|
lo = (x_flat.to(cd) @ Ad.T) @ Bd.T * mult
|
||||||
if sl is not None:
|
if sl is not None:
|
||||||
if lo.shape[1] == (se - sl):
|
if lo.shape[1] != (se - sl):
|
||||||
out[:, sl:se] += lo
|
raise ValueError(
|
||||||
|
f"LoRA output width {lo.shape[1]} "
|
||||||
|
f"doesn't match target slice width "
|
||||||
|
f"{se - sl}"
|
||||||
|
)
|
||||||
|
out[:, sl:se] += lo
|
||||||
elif lo.shape[1] == out.shape[1]:
|
elif lo.shape[1] == out.shape[1]:
|
||||||
out += lo
|
out += lo
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"LoRA output shape {lo.shape} "
|
||||||
|
f"incompatible with {out.shape}"
|
||||||
|
)
|
||||||
|
|
||||||
if self.bias is not None:
|
if self.bias is not None:
|
||||||
out += self.bias.to(device=dev, dtype=out.dtype)
|
out += self.bias.to(device=dev, dtype=out.dtype)
|
||||||
|
|||||||
@ -14,6 +14,7 @@ except ImportError:
|
|||||||
_SCIPY_AVAILABLE = False
|
_SCIPY_AVAILABLE = False
|
||||||
|
|
||||||
_HADAMARD_CACHE: dict = {}
|
_HADAMARD_CACHE: dict = {}
|
||||||
|
_HADAMARD_MAX_SIZE = 64 # Maximum number of cached (size, device, dtype) entries
|
||||||
|
|
||||||
|
|
||||||
def build_hadamard(
|
def build_hadamard(
|
||||||
@ -38,14 +39,20 @@ def build_hadamard(
|
|||||||
H_np = _scipy_hadamard(size)
|
H_np = _scipy_hadamard(size)
|
||||||
H = torch.tensor(H_np, dtype=dtype, device=device) / (size ** 0.5)
|
H = torch.tensor(H_np, dtype=dtype, device=device) / (size ** 0.5)
|
||||||
else:
|
else:
|
||||||
|
# Pure-PyTorch Sylvester construction
|
||||||
H = torch.tensor([[1.0]], dtype=dtype, device=device)
|
H = torch.tensor([[1.0]], dtype=dtype, device=device)
|
||||||
n = 1
|
n = 1
|
||||||
while n < size:
|
while n < size:
|
||||||
H = torch.cat([torch.cat([H, H], dim=1),
|
top = torch.cat([H, H], dim=1)
|
||||||
torch.cat([H, -H], dim=0)], dim=0)
|
bottom = torch.cat([H, -H], dim=1)
|
||||||
|
H = torch.cat([top, bottom], dim=0)
|
||||||
n *= 2
|
n *= 2
|
||||||
H = H / (size ** 0.5)
|
H = H / (size ** 0.5)
|
||||||
|
|
||||||
|
# Enforce cache size cap (evict oldest entry)
|
||||||
|
if len(_HADAMARD_CACHE) >= _HADAMARD_MAX_SIZE:
|
||||||
|
_HADAMARD_CACHE.pop(next(iter(_HADAMARD_CACHE)))
|
||||||
|
|
||||||
_HADAMARD_CACHE[cache_key] = H
|
_HADAMARD_CACHE[cache_key] = H
|
||||||
return H
|
return H
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user