Skip to content

feat: add an XPU graph backend - #33

Merged
PatKamin merged 13 commits into
intel:mainfrom
lslusarczyk:graph
Oct 23, 2026
Merged

PatKamin merged 13 commits into
intel:mainfrom
lslusarczyk:graph

Conversation

@lslusarczyk

Copy link
Copy Markdown
Contributor

Add an XPU graph backend

The backend records the module once during tuning and replays that recording for inference.

Replay needs static tensor shapes.
A dynamic batch rejects this backend.

It sits next to Torch Inductor in the default strategies.
Timing waits for the device, so a replay is measured after the GPU finishes.

@lslusarczyk
lslusarczyk requested a review from a team as a code owner October 21, 2026 11:41
@lukaszstolarczuk

Copy link
Copy Markdown
Contributor

pls fix dco and rebase

The backend records the module once during tuning and replays that recording for inference.

Replay needs static tensor shapes.
A dynamic batch rejects this backend.

It sits next to Torch Inductor in the default strategies.
Timing waits for the device, so a replay is measured after the GPU finishes.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
Comment thread .claude/skills/torch-tweak-assistant/SKILL.md Outdated
Comment thread torch_tweak/torch/task/profiling/measuring_strategy.py Outdated
Comment thread torch_tweak/torch/backend/xpu_graph_backend.py Outdated

def _build(self, module: nn.Module, graph_spec: GraphSpec, data: list[Sample], cache_dir: Path) -> Backend:
"""Records the XPU graph once and checks it against eager."""
if graph_spec.has_dynamic_axis():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth considering to exclude only dim axes and build and record batch axes, each batch size is profilied independently anyway

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reported SPJT-490 for this

Comment thread torch_tweak/torch/tune_strategy/first_wins_strategy.py
Comment thread tests/unit/torch/backend/test_xpu_graph_backend.py
Comment thread tests/unit/torch/backend/test_xpu_graph_backend.py
lslusarczyk and others added 11 commits October 23, 2026 10:06
TorchInductorBackend and TorchAOBackend saved every recorded sample. A sample holding a transformers
DynamicCache, as recorded during generate, made save fail. These samples only compile the module ahead
of the first call, so they are left out and the first call compiles instead.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
wrap() named each Module after the last segment of its object path.
Siblings such as layers.0.mlp and layers.1.mlp shared the name "mlp".
MODULE_REGISTRY is keyed by name, so only the last one was registered.
The others were never tuned and kept recording samples on every call.
The cache directory, keyed by the same name, collided as well.

The wrapper name is now the object path, which is unique within one inspection.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
It requires minimum Python 3.11 version.

Signed-off-by: Lukasz Stolarczuk <lukasz.stolarczuk@intel.com>
Drop the Simple line from every backend in the skill.
Move the synchronize comment to the sync after the model call.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
Inputs the recording cannot take run on the original module.
A larger batch after tuning reaches the backend, so it no longer raises.

FirstWinsStrategy tries the XPU graph before Torch Inductor.
Inductor almost always builds, so the graph never ran in second place.

Tests cover deactivate then activate, deploy after a checkpoint load, and a larger batch.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
The fallback output equals eager, so comparing to eager cannot see it.
An autouse fixture records every fallback call.
A test that does not take eager_calls fails when the fallback runs.
The fallback tests check which inputs fell back.

The tune tests compare against a deep copy made before tuning.
After tune, calls of the original module go through the selected backend.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
_live_leaves checks the inputs and returns their flattened leaves.
_copy_into copies those leaves, so infer no longer flattens args and kwargs twice.
_load_inputs copies nothing when an input does not fit.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
The scale=3.0 call always falls back.
len(eager_calls) == 1 already shows the first call replayed.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
test_tune_module calls a larger batch, then the tuned batch.
Only the larger batch runs the original module.
The skill lists the new FirstWinsStrategy order.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
The default FirstWinsStrategy tries XPUGraphBackend first.

Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
@PatKamin

Copy link
Copy Markdown
Contributor

Please, rebase

@PatKamin
PatKamin merged commit b5ddfd0 into intel:main Oct 23, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants