Repository navigation
feat(xpu_graph): batch sizes, per batch size routing, and Inductor kernels - #47
Draft
lslusarczyk wants to merge 4 commits into
Draft
lslusarczyk wants to merge 4 commits into
lslusarczyk wants to merge 4 commits into
Conversation
A graph spec with a batch axis now records graphs for batch sizes 1, 2, 4, and every multiple of 8 up to the largest batch size seen during tuning. max_recorded_batch_size caps that size at 256 by default. A call pads its batch with zeros to the smallest recorded size that holds it. A larger batch replays in chunks. All graphs share one memory pool and one input buffer. Tuning runs eager once on the largest batch and compares every graph with it, full and partly padded. Modules whose rows depend on other rows are rejected. Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
The first call of a new batch size can compile, for example in Torch Inductor. Saturation counted that call, so a backend looked saturated and stopped profiling early. On MobileNetV3, Inductor stopped at batch size 8 and never ran 16, 32, or 64. The stop strategy now sees the same measured window that the reported throughput uses. Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
HighestThroughputStrategy kept one backend for every batch size. It chose by peak throughput, which is usually at the largest batch size. A backend that was faster at small batch sizes, such as an XPU graph, lost them. The strategy now compares backends at every profiled batch size. Another backend takes a range when it is at least 10% faster there. BatchSizeRouterBackend holds the routed backends and sends each call by its batch size. It saves and loads every routed backend in a checkpoint. On MobileNetV3 it routes batch sizes 1 to 16 to the XPU graph and larger ones to Inductor. Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
…ctor XPUGraphBackendConfig(compile_with_inductor=True) compiles the module with Torch Inductor and records the compiled kernels in the XPU graphs. Replay runs the fused kernels without a Python launch per kernel. It is the XPU counterpart of torch.compile(mode="reduce-overhead") on CUDA. Compilation runs in the warmup before each recording. Inductor compiles three times for all recorded sizes. Signed-off-by: Łukasz Ślusarczyk <lukasz.slusarczyk@intel.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
XPU graphs now serve a dynamic batch, record Inductor kernels, and win only the batch sizes where they are faster.
Grid of batch sizes
The XPU graph backend records graphs for batch sizes 1, 2, 4, and every multiple of 8, up to the largest batch size seen during tuning.
max_recorded_batch_sizecaps that size at 256, which is 35 graphs.vLLM and TensorRT-LLM use the same grid.
A call pads its batch with zeros to the smallest recorded size that holds it.
A larger batch replays in chunks.
All graphs share one memory pool and one input buffer.
Tuning runs eager once on the largest batch and compares every graph with prefixes of it, full and padded.
Inductor kernels
XPUGraphBackendConfig(compile_with_inductor=True)records the kernels Torch Inductor generates.Replay runs the fused kernels without a Python launch per kernel.
It is the XPU counterpart of
torch.compile(mode="reduce-overhead")on CUDA.Inductor compiles three times for all recorded sizes.
Routing by batch size
HighestThroughputStrategykept one backend for every batch size, chosen by peak throughput.An XPU graph lost the small batch sizes it was faster at.
Another backend now takes a range of batch sizes when it is at least 10% faster there.
BatchSizeRouterBackendholds the routed backends, sends each call by its batch size, and saves them in a checkpoint.Profiling fix
Saturation counted the first call of a new batch size, which can compile.
Inductor looked saturated and stopped profiling at batch size 8.
The stop strategy now judges the measured window, like the reported throughput.
Performance
Latency in ms on Arc Pro B70, fp32, torch 2.14.1+xpu, by batch size.
Auto is
HighestThroughputStrategyover all four backends.XPU graph + Inductor is the fastest single backend for launch-bound models.
It ties Inductor on large batches, except where padding adds rows: ViT batch 17 runs the graph for 24.
Auto lands on the fastest backend at each batch size.
On ResNet-18 it routes 1 to 4 to XPU graph + Inductor and 5 and up to Inductor.