Human Note
Use per-callable storage keys in SAC's dispatch modes so that each inductor_compiled_code region gets its own FIFO queue. Previously all compiled regions shared one queue keyed by the HOP identity, causing wrong cached values to be returned when a region was skipped during recompute due to global cache state. Fixes )
Summary
When wrap_inductor_compiled_regions=True and SAC (Selective Activation Checkpointing) is used, all inductor_compiled_code HOP calls shared a single FIFO queue keyed only by the HOP identity. If a compiled region was skipped during SAC recompute (e.g. due to a cache hit on a global dict), the queue returned the wrong cached value, causing DTensor.__tensor_unflatten__ to fail with RuntimeError: Only Tensors of floating point and complex dtype can require gradients.
Root Cause
SAC stores cached op outputs in a defaultdict(list) keyed by func. All inductor_compiled_code calls—regardless of which compiled region they wrap—shared one queue entry under the same key.
Forward (cache miss): two inductor_compiled_code calls fire → queue has [int32_output, float_dtensor_output].
Recompute (cache hit): first compiled region is skipped → only one inductor_compiled_code call fires → pops int32_output instead of float_dtensor_output → crash.
Fix
Added _sac_storage_key(func, args) in torch/utils/checkpoint.py that returns (func, callable.idx) for inductor_compiled_code and plain func for everything else. Each compiled region now gets its own FIFO queue, so skipping one region during recompute doesn't corrupt another's queue.
Files changed:
torch/utils/checkpoint.py— Added_sac_storage_key(), used it in both_CachingTorchDispatchModeand_CachedTorchDispatchModetest/dynamo/test_wrap_inductor_compiled_regions.py— Addedtest_sac_cached_value_fifo_mismatchregression test
Repro Script
"""Minimal self-contained repro for DTensor int tensor + SAC + compile bug."""
import os
os.environ["RANK"] = "0"
os.environ["WORLD_SIZE"] = "1"
os.environ["LOCAL_RANK"] = "0"
os.environ["MASTER_ADDR"] = "localhost"
os.environ["MASTER_PORT"] = "29500"
import torch
import torch.distributed as dist
import torch.utils.checkpoint
from functools import partial
from torch.distributed.device_mesh import init_device_mesh
from torch.distributed.tensor import DTensor, Replicate
from torch.nn.attention.flex_attention import create_block_mask, flex_attention
from torch.utils.checkpoint import CheckpointPolicy
torch._inductor.config.wrap_inductor_compiled_regions = True
dist.init_process_group(backend="fake", init_method="env://", world_size=1, rank=0)
device = "cuda" if torch.cuda.is_available() else "cpu"
mesh = init_device_mesh(device, mesh_shape=(1,), mesh_dim_names=("fsdp",))
_SAVE = {torch.ops.higher_order.flex_attention.name(): None, "inductor_compiled_code": None}
def ac_policy(ctx, op, *args, **kwargs):
if (isinstance(op, torch._ops.HigherOrderOperator) and op.name() in _SAVE) or op in _SAVE:
return CheckpointPolicy.MUST_SAVE
return CheckpointPolicy.PREFER_RECOMPUTE
L = 64
_compiled_create_block_mask = torch.compile(create_block_mask, dynamic=False, fullgraph=True)
_compiled_flex_attention = torch.compile(flex_attention, mode="default", fullgraph=True, dynamic=False)
def causal(b, h, q, k):
return q >= k
_mask_cache = {}
def inner_fn(q, mask):
ql = q.to_local()
out = _compiled_flex_attention(query=ql, key=ql, value=ql, block_mask=mask)
return DTensor.from_local(out, device_mesh=q.device_mesh, placements=q.placements)
inner_fn = torch.compile(inner_fn, mode="default", fullgraph=True, dynamic=False)
def outer_fn(x):
if "m" not in _mask_cache:
_mask_cache["m"] = _compiled_create_block_mask(
mask_mod=causal, B=None, H=None,
Q_LEN=L, KV_LEN=L, BLOCK_SIZE=128, device=x.device,
)
return inner_fn(x, _mask_cache["m"])
context_fn = partial(torch.utils.checkpoint.create_selective_checkpoint_contexts, ac_policy)
x = DTensor.from_local(
torch.randn(1, 1, L, L, device=device, dtype=torch.bfloat16, requires_grad=True),
mesh, (Replicate(),),
)
try:
out = torch.utils.checkpoint.checkpoint(
outer_fn, x, use_reentrant=False, context_fn=context_fn,
)
out.sum().backward()
print("PASS - no error")
except RuntimeError as e:
import traceback
traceback.print_exc()
if "Only Tensors of floating point and complex dtype" in str(e):
print("\nFAIL - DTensor constructor error reproduced!")
else:
print(f"\nDifferent error: {e}")
finally:
dist.destroy_process_group()Before fix:
RuntimeError: Only Tensors of floating point and complex dtype can require gradients
FAIL - DTensor constructor error reproduced!
After fix:
PASS - no error
Test Results
- Regression test fails before fix: Yes —
RuntimeError: Only Tensors of floating point and complex dtype can require gradients - Regression test passes after fix: Yes
- All 21 existing tests in
test_wrap_inductor_compiled_regions.pypass: Yes - Original CUDA repro script passes: Yes
Remaining Risks
- This fix only handles
inductor_compiled_code. Other HOPs that branch on global state could still cause FIFO mismatches. For a fully general solution, users would need a "recompute tape" mechanism (record decisions during forward, replay during recompute). This is an additive feature that can be built separately. - The fix relies on
InductorCompiledCallable.idxbeing stable between forward and recompute. This is guaranteed because dynamo caches the compiled callable object.
Fixes with human review.
Pull Request resolved:
Community-Analysen & Experten-Meinungen 0
Verwandte Story-Cluster & Quellen (Vektor-KI)
Ähnliche Beiträge
Auch interessante Nachrichten trunk/c15e9774278597951aa402693c1bbcb6c8c7b9e8: Fix SAC FIFO mismatch for inductor_compiled_code HOP (#177198)
Thematisch verwandte Begriffe: trunkc15e9774278597951aa402693c1bbcb6c8c7b9e8, FIFO, mismatch, inductorcompiledcode · 6 Treffer
Generative AI: This Is How You Can Use ChatGPT Safely
Major Cyber Attacks, Data Breaches, Ransomware Attacks in August 2026
LLM Fallback: What Happens When Your Model Goes Down
OpenAI’s Apple Messages Tool Raises Privacy Concerns Over Decrypted Chats
Hackers Breach 5,000 Dropbox Accounts Through Lenovo ID Authentication Flaw
Meet Manic: The Android Malware With a Sneaky Backup Plan
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
SOCIAL SHARE CARD GENERATOR