Skip to content

Commit 6cfb8e3

Browse files
Fridah-nvclaude
andcommitted
refactor(hf_ptq): drop the offloaded-weight pin, which the layerwise path does not need
_pin_externally_read_params existed because Kimi-K3's _apply_attn_res reads the residual proj/norm weights from the decoder layer's forward rather than calling those modules, so accelerate leaves them on meta. That is real for a plain full forward, but not for this pipeline: every forward in the calibration loop runs inside persistent_materialization(layer), which materializes the layer subtree including those modules, and the only forward outside a window is the bootstrap capture, which early-stops before reaching them. Measured on midi-K3 with offload genuinely engaged (--max_gpu_memory_gb 0.5 --max_cpu_memory_gb 0.1): pin active exit=0 shards=9 OFFLOAD=1 PINNED=1 meta_err=0 pin disabled exit=0 shards=9 OFFLOAD=1 PINNED=0 meta_err=0 Exports equivalent: 2922/2922 keys, the single flagged tensor being a NaN from the fixture's random init (identical NaN masks, all 31 finite entries equal). midi-K3 does carry the modules in question -- 8 mlp_res_proj, 8 mlp_res_norm, 8 self_attention_res_proj, 1 output_attn_res_proj -- so the control exercises the pattern rather than skipping it. An earlier run of this comparison was void: at --max_gpu_memory_gb 1 nothing was offloaded, so both arms took the same resident path. The budget above is the range where accelerate offloads part of the model; below roughly 0.05 it refuses outright. Removing it also removes the hardcoded six-suffix Kimi-K3 module list from a shared example helper, which applied to every offloaded run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Fridah-nv <201670829+Fridah-nv@users.noreply.github.com>
1 parent 363b79b commit 6cfb8e3

1 file changed

Lines changed: 0 additions & 61 deletions

File tree

examples/hf_ptq/example_utils.py

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -741,61 +741,6 @@ def _force_attn_implementation(model, attn_implementation: str) -> None:
741741
print(f" {line}")
742742

743743

744-
#: Modules whose weights are read from *another* module's forward, so accelerate never
745-
#: materializes them. Kimi-K3's ``_apply_attn_res`` does
746-
#: ``norm.weight.float() * proj.weight.squeeze(0).float()`` from the decoder layer's
747-
#: forward, reaching into these six children (``modeling_kimi_linear.py``, three call
748-
#: sites). Each is one row -- ``(1, hidden)`` and ``(hidden,)`` -- so pinning all of them
749-
#: on a 93-layer model costs single-digit MB.
750-
_EXTERNALLY_READ_PARAM_SUFFIXES = (
751-
"self_attention_res_proj",
752-
"self_attention_res_norm",
753-
"mlp_res_proj",
754-
"mlp_res_norm",
755-
"output_attn_res_proj",
756-
"output_attn_res_norm",
757-
)
758-
759-
760-
def _pin_externally_read_params(
761-
model, suffixes: tuple[str, ...] = _EXTERNALLY_READ_PARAM_SUFFIXES
762-
) -> int:
763-
"""Make offloaded weights that are read outside their own forward permanently resident.
764-
765-
accelerate materializes an offloaded weight in *that module's* pre-forward hook and
766-
returns it to meta in the matching post-forward. A weight read from a sibling's forward
767-
is therefore on meta at the moment it is used, which surfaces as
768-
``Tensor on device meta is not on the expected device cuda:0``.
769-
770-
Setting the tensor is not enough on its own: ``post_forward`` walks the module's tensors
771-
and pushes every one back to meta, so the hook has to go. Detaching alone is not enough
772-
either -- ``AlignDevicesHook.detach_hook`` restores each tensor to
773-
``original_devices[name]`` and *skips* meta, which is precisely what a disk-offloaded
774-
param has, so it would be left on meta. Retargeting ``original_devices`` at the
775-
execution device first makes detach do the materialization itself, using accelerate's
776-
own code path rather than a hand-rolled copy.
777-
778-
Safe because these modules' ``forward`` is never called -- only their raw ``.weight`` is
779-
read -- so removing the hook removes nothing that was doing work.
780-
781-
Returns the number of modules pinned.
782-
"""
783-
from accelerate.hooks import remove_hook_from_module
784-
785-
pinned = 0
786-
for name, module in model.named_modules():
787-
if not name.endswith(suffixes):
788-
continue
789-
hook = getattr(module, "_hf_hook", None)
790-
if hook is None or not getattr(hook, "offload", False):
791-
continue
792-
device = hook.execution_device
793-
hook.original_devices = dict.fromkeys(getattr(hook, "original_devices", {}), device)
794-
remove_hook_from_module(module)
795-
pinned += 1
796-
return pinned
797-
798-
799744
def _get_config_dtype(config):
800745
config_dtype = (
801746
getattr(config, "dtype", None) or getattr(config, "torch_dtype", None) or torch.bfloat16
@@ -1066,12 +1011,6 @@ def has_pack_quantized_config(config):
10661011
if attn_implementation is not None:
10671012
_force_attn_implementation(model, attn_implementation)
10681013

1069-
# Offloaded weights that a sibling's forward reads would otherwise be on meta when used.
1070-
if _disk_offload:
1071-
n_pinned = _pin_externally_read_params(model)
1072-
if n_pinned:
1073-
print(f"Pinned {n_pinned} externally-read modules so offload cannot meta them.")
1074-
10751014
if has_pack_quantized_config(hf_config):
10761015
_unpack_compressed_linear_weights(model, ckpt_path)
10771016

0 commit comments

Comments
 (0)