RuntimeError: torch.compile: function 'forward' failed with a graph break. Falling back to eager mode. Consider rewriting the function to avoid dynamic control flow.
ID: pytorch/torch-compile-graph-break
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| torch>=2.1 | active | — | — | — |
| torch>=2.3 | active | — | — | — |
| Python 3.11 | active | — | — | — |
Root Cause
torch.compile encountered a graph break (e.g., dynamic control flow, unsupported operations, or Python-side side effects) that prevents the entire computation graph from being captured, forcing a fallback to eager mode and potentially reducing performance.
generic中文
torch.compile 遇到图断裂(例如动态控制流、不支持的操作或 Python 端副作用),导致无法捕获整个计算图,被迫回退到 eager 模式,并可能降低性能。
Official Documentation
https://pytorch.org/docs/stable/torch.compiler.html#debugging-graph-breaksWorkarounds
-
85% success Refactor the forward method to remove dynamic control flow. Replace if statements with torch.where or masked operations: # Before (causes graph break): if x.sum() > 0: y = x * 2 else: y = x + 1 # After (no graph break): mask = (x.sum() > 0).float() y = mask * (x * 2) + (1 - mask) * (x + 1)
Refactor the forward method to remove dynamic control flow. Replace if statements with torch.where or masked operations: # Before (causes graph break): if x.sum() > 0: y = x * 2 else: y = x + 1 # After (no graph break): mask = (x.sum() > 0).float() y = mask * (x * 2) + (1 - mask) * (x + 1) -
80% success Use torch.compiler.disable() decorator on specific submodules that cause graph breaks, while keeping the rest compiled: @torch.compiler.disable def custom_op(x): return my_python_function(x) model = torch.compile(model)
Use torch.compiler.disable() decorator on specific submodules that cause graph breaks, while keeping the rest compiled: @torch.compiler.disable def custom_op(x): return my_python_function(x) model = torch.compile(model) -
75% success Enable torch._dynamo.config.verbose=True and torch._dynamo.config.suppress_errors=True to get detailed logs on where the graph break occurs: import torch._dynamo torch._dynamo.config.verbose = True torch._dynamo.config.suppress_errors = True
Enable torch._dynamo.config.verbose=True and torch._dynamo.config.suppress_errors=True to get detailed logs on where the graph break occurs: import torch._dynamo torch._dynamo.config.verbose = True torch._dynamo.config.suppress_errors = True
中文步骤
Refactor the forward method to remove dynamic control flow. Replace if statements with torch.where or masked operations: # Before (causes graph break): if x.sum() > 0: y = x * 2 else: y = x + 1 # After (no graph break): mask = (x.sum() > 0).float() y = mask * (x * 2) + (1 - mask) * (x + 1)Use torch.compiler.disable() decorator on specific submodules that cause graph breaks, while keeping the rest compiled: @torch.compiler.disable def custom_op(x): return my_python_function(x) model = torch.compile(model)Enable torch._dynamo.config.verbose=True and torch._dynamo.config.suppress_errors=True to get detailed logs on where the graph break occurs: import torch._dynamo torch._dynamo.config.verbose = True torch._dynamo.config.suppress_errors = True
Dead Ends
Common approaches that don't work:
-
Disabling torch.compile entirely with torch.compiler.reset()
95% fail
This removes the performance benefits of compilation and does not address the underlying code pattern that causes graph breaks.
-
Adding @torch.jit.script decorator on top of torch.compile
90% fail
torch.jit.script and torch.compile are different systems; mixing them can cause conflicts and unexpected behavior, not fixing the graph break.
-
Using torch.inference_mode() to disable autograd entirely
85% fail
While inference mode reduces overhead, it does not resolve graph breaks caused by dynamic control flow in the model's forward method.