|
| 1 | +# Graph Mode Troubleshooting |
| 2 | + |
| 3 | +This guide helps debug common issues when using Graph execution mode in CoreAI-Opt. |
| 4 | + |
| 5 | +A `quantizer.prepare()` failure in graph mode happens in one of two stages, and the fix differs sharply between them. The first thing to do is figure out **which** stage is failing. |
| 6 | + |
| 7 | +## Step 1: Diagnose — does `torch.export.export` succeed? |
| 8 | + |
| 9 | +`Quantizer.prepare()` first calls `torch.export.export` to trace the model into an FX graph, then applies quantization annotations on the resulting graph and runs `torchao`'s `prepare_qat_pt2e`. To localize the failure, run the export step directly with the same arguments `prepare()` would use: |
| 10 | + |
| 11 | +```python |
| 12 | +import torch |
| 13 | + |
| 14 | +with torch.no_grad(): # matches export_with_no_grad=True (the prepare() default) |
| 15 | + exported_program = torch.export.export(model, example_inputs) |
| 16 | +``` |
| 17 | + |
| 18 | +The result of this experiment determines which path to follow: |
| 19 | + |
| 20 | +- **Export fails.** Go to [If `torch.export.export` fails](#if-torch-export-export-fails). The model isn't `torch.export`-compatible as written; the workarounds in Steps 2-3 may help. |
| 21 | +- **Export succeeds but `prepare()` still fails.** Go to [If `prepare()` fails after a successful export](#if-prepare-fails-after-a-successful-export). |
| 22 | + |
| 23 | +## If `torch.export.export` fails |
| 24 | + |
| 25 | +### Step 2: Try `export_with_no_grad=False` |
| 26 | + |
| 27 | +The default `export_with_no_grad=True` wraps the export call in `torch.no_grad()`. For some models, this context modifies tracing behavior and causes guard failures. |
| 28 | + |
| 29 | +```python |
| 30 | +prepared = quantizer.prepare( |
| 31 | + example_inputs=(input_tensor,), |
| 32 | + export_with_no_grad=False, |
| 33 | +) |
| 34 | +``` |
| 35 | + |
| 36 | +### Step 3: Use dynamic shapes for shape-related errors |
| 37 | + |
| 38 | +If the error mentions shape constraints, guards, or symbolic dimensions, the model likely has inputs with variable dimensions (e.g., sequence length, batch size). Specify `dynamic_shapes` to tell the exporter which dimensions can vary: |
| 39 | + |
| 40 | +```python |
| 41 | +from torch.export.dynamic_shapes import Dim |
| 42 | + |
| 43 | +# Example: dynamic batch dimension |
| 44 | +prepared = quantizer.prepare( |
| 45 | + example_inputs=(input_tensor,), |
| 46 | + dynamic_shapes={"x": (Dim.AUTO, Dim.STATIC, Dim.STATIC, Dim.STATIC)}, |
| 47 | +) |
| 48 | + |
| 49 | +# Example: dynamic sequence length with a max constraint |
| 50 | +import torch.export |
| 51 | + |
| 52 | +dynamic_shapes = { |
| 53 | + "input_ids": {1: torch.export.Dim("seq_len", max=2048)}, |
| 54 | + "attention_mask": {1: torch.export.Dim("seq_len", max=2048)}, |
| 55 | +} |
| 56 | +prepared = quantizer.prepare( |
| 57 | + example_inputs=(input_ids, attention_mask), |
| 58 | + dynamic_shapes=dynamic_shapes, |
| 59 | +) |
| 60 | +``` |
| 61 | + |
| 62 | +For full details on dynamic shapes, see the [PyTorch Export Tutorial -- Dynamic Shapes](https://docs.pytorch.org/tutorials/intermediate/torch_export_tutorial.html#constraints-dynamic-shapes). |
| 63 | + |
| 64 | +If Steps 2-3 don't resolve the export failure (e.g., the model has data-dependent control flow that `torch.export` cannot capture), see [Fall back to EAGER execution mode](#fall-back-to-eager-execution-mode) below. |
| 65 | + |
| 66 | +## If `prepare()` fails after a successful export |
| 67 | + |
| 68 | +After `torch.export.export` returns, `Quantizer.prepare()` applies coreai-opt's annotation pass and then calls into torch's `prepare_qat_pt2e` API. If the error you're seeing comes from `prepare_qat_pt2e` itself, it is a torch-side issue — refer to the [`torchao` documentation](https://docs.pytorch.org/ao/stable/) and report against torch. |
| 69 | + |
| 70 | +If the error does **not** come from `prepare_qat_pt2e` (i.e. it originates inside coreai-opt's annotation pass), it likely indicates a bug on our end. **Please file an issue on GitHub** with the error message and a minimal reproducer. In the meantime, [fall back to eager mode](#fall-back-to-eager-execution-mode) below — eager bypasses the entire graph-mode pipeline. |
| 71 | + |
| 72 | +## Fall back to EAGER execution mode |
| 73 | + |
| 74 | +EAGER mode bypasses `torch.export` entirely and uses runtime tracing instead. It is the common fallback for both export failures that can't be worked around with Steps 2-3 and post-export `prepare()` failures. |
| 75 | + |
| 76 | +```python |
| 77 | +from coreai_opt.quantization import ExecutionMode |
| 78 | + |
| 79 | +config = QuantizerConfig.presets.w8() |
| 80 | +config.execution_mode = ExecutionMode.EAGER |
| 81 | +quantizer = Quantizer(model, config) |
| 82 | +prepared = quantizer.prepare(example_inputs=(input_tensor,)) |
| 83 | +``` |
| 84 | + |
| 85 | +See [Choosing between graph and eager mode](../quantization/overview.md#choosing-between-graph-and-eager-mode) for the trade-offs between the two modes. |
| 86 | + |
| 87 | +## External Resources |
| 88 | + |
| 89 | +- [PyTorch Export Tutorial](https://docs.pytorch.org/tutorials/intermediate/torch_export_tutorial.html) |
| 90 | +- [Dynamic Shapes](https://docs.pytorch.org/tutorials/intermediate/torch_export_tutorial.html#constraints-dynamic-shapes) |
0 commit comments