Repository navigation
[executorch][native-ggml] Add end-to-end op tests for the ggml engine - #23752
Merged
meta-codesync[bot] merged 4 commits intoOct 14, 2026
Merged
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/23752
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit e30ed9b with merge base 0a4a05e ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
This was referenced Oct 13, 2026
Merged
Merged
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
… ggml Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * __->__ #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The HuggingFace static-cache Llama path on the ggml engine was only covered op by op, not end to end. Adds an end-to-end test of a tiny quantized HuggingFace Llama: prefill and two decode steps on one executable, compared with eager. The test runner can now resize inputs and run several steps on one executable, so mutable state carries over. Authored with Claude and Codex assistance. Differential Revision: D123796924 Pull Request resolved: #23757
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…nd, including HIP Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * __->__ #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The ggml engine should run on AMD as well as NVIDIA GPUs without a backend-specific code path for each one. The engine picks a GPU from ggml's device registry, so the same source runs on CPU, CUDA or HIP, depending only on which ggml backends are linked. Graph inputs are placed on the primary backend. Authored with Claude and Codex assistance. Differential Revision: D123796925 Pull Request resolved: #23758
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…gml engine Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * __->__ #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 fp32 vision models such as torchvision MobileNetV2 and ResNet50 should run on the ggml engine, on CPU and GPU. The ggml engine runs 2D convolution (regular and depthwise), inference batch norm, ReLU and ReLU6 (including in place), max pooling and trailing-dim mean. It rejects arguments outside what it supports. Linear and RMS norm also handle F16 and BF16 inputs, weights and biases. The test runner can time repeated executions. Authored with Claude and Codex assistance. Differential Revision: D123796926 Pull Request resolved: #23759
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…out an extra copy Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * __->__ #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 Loading ggml engine constants copied each one twice, raising load time and peak memory, especially for fp32 models on CPU and quantized Llama. The ggml engine loads constants with fewer copies, reading the package's own bytes where it can, and reports how many bytes still needed a heap copy. Authored with Claude and Codex assistance. Differential Revision: D123796927 Pull Request resolved: #23760
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * __->__ #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 Every execute on the ggml engine rebuilt, scheduled and allocated its graph, even when the input shapes matched the previous call, as in LLM decode. The ggml engine keeps a configurable number of built graphs per executable, keyed by input shapes, and replays them with fresh input bytes. Row indices that feed gathers and cache writes are rechecked on every replay. Authored with Claude and Codex assistance. Differential Revision: D123796928 Pull Request resolved: #23761
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * __->__ #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 GGUF Q4_K_M checkpoints store some weights, such as the token embedding and some projections, as Q6_K, which the ggml engine did not accept. The ggml engine accepts GGUF Q6_K weights next to Q4_K and runs them on ggml's own Q6_K kernels, checking the block layout at load. Authored with Claude and Codex assistance. Differential Revision: D123796929 Pull Request resolved: #23762
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…oss ops Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * __->__ #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 An HF static-cache Llama passes one mask and one set of cache positions to every layer, and the ggml lowering rebuilt the same conversions for each consumer. The ggml engine reuses integer casts of immutable values and converted attention masks across ops, and invalidates them on any in-place write to their storage. An engine option prints each built graph's op counts, so tests can check that a rewrite fired. Authored with Claude and Codex assistance. Differential Revision: D123796930 Pull Request resolved: #23763
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * __->__ #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 Exported Llama MLPs spell `silu(gate) * up` with `aten.silu` or as `gate * sigmoid(gate) * up`. Lowered literally, that costs several elementwise kernels per layer and misses ggml's fused paths. The ggml engine recognizes these SiLU and SwiGLU spellings from the arithmetic alone and runs them as single ggml ops. Broadcasting products are left as they are. Authored with Claude and Codex assistance. Differential Revision: D123796931 Pull Request resolved: #23764
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * __->__ #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The ggml lowering materialized every copying op, including permutes of size-1 axes, clones and same-type casts of contiguous tensors, which adds a kernel per copy at every decode step. A copy of contiguous storage that is neither persistent nor written in place now shares that storage. Copies that a later in-place write could observe stay real copies. Authored with Claude and Codex assistance. Differential Revision: D123796932 Pull Request resolved: #23765
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * __->__ #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 With an FP16 KV cache, every K and V cache write ran a separate F32-to-F16 cast kernel before the write. FP16 cache writes of freshly cast F32 values no longer run a separate cast, with bit-identical results. Sources that could change before the write keep their cast. Authored with Claude and Codex assistance. Differential Revision: D123796933 Pull Request resolved: #23766
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * __->__ #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 Each call downloaded every output into pageable host memory, which GPU drivers bounce through their own pinned buffer. Outputs are staged in one reusable area per executable, pinned when the device offers pinned host memory. Changing inputs or a failed call now invalidates staged outputs, so a stale output cannot be read. Authored with Claude and Codex assistance. Differential Revision: D123796934 Pull Request resolved: #23767
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * __->__ #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 A PTN is meant to run unchanged on every native engine, but nothing checked that one exported PTN gives the same answers on each engine. Adds an end-to-end test that exports each model, runs it on the ggml and Vulkan engines, and compares both with eager PyTorch: MobileNetV2 and a tiny HuggingFace Llama with float and GGUF weights, plus an FP16 KV cache on ggml only (native-vk's HF attention lowering needs FP32 caches). The test runners now share one engine-neutral driver. Authored with Claude and Codex assistance. Differential Revision: D123796936 Pull Request resolved: #23768
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…engines Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * __->__ #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The same Llama app existed twice, once per engine, and the copies had already drifted. Every app fix had to be made twice, and more engines are coming. Adds one engine-neutral decoder-only LLM runner next to the HuggingFace exporter, with a few-line front end per engine (Vulkan, ggml CPU/CUDA/HIP), and removes the two copies. The Vulkan runner now reports decode per step and stops at the KV-cache length, as the ggml one did. Authored with Claude and Codex assistance. Differential Revision: D123796942 Pull Request resolved: #23769
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…eads Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * __->__ #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The Vulkan engine runs functional in-place ops such as `relu_` out of place, and refused any whose input was a view. So a ReLU after a reshape, which the native passes emit, could not compile. In-place ops whose input is a view now run out of place when nothing else reads the view or anything up its alias chain. They are still refused when something else does. Authored with Claude and Codex assistance. Differential Revision: D124032906 Pull Request resolved: #23770
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * __->__ #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 ET-VK views keep the sizes they were built with, so the Vulkan engine rejected any view of a dynamically shaped source other than `aten.view`. Models that split heads or build masks over a dynamic sequence stopped at compile. Views of dynamically shaped sources (permute, select, squeeze, unsqueeze, alias) now run as copy kernels that follow resizes. They keep their source's layout, and negative dims are supported. Authored with Claude and Codex assistance. Differential Revision: D124032907 Pull Request resolved: #23771
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…d layout Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * __->__ #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 ET-VK's layer norm requires its input and output to share a packed layout, but layout assignment could give them different ones, so a layer norm of a graph input feeding a linear failed at compile. Layer norm keeps its input and output in one packed layout, like the elementwise ops, with no extra copy. Authored with Claude and Codex assistance. Differential Revision: D124032908 Pull Request resolved: #23772
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * __->__ #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The native passes emit GELU and sigmoid after a linear as in-place ops, which the Vulkan engine did not map, so they failed as unsupported. `gelu_` and `sigmoid_` run out of place like `relu_`, with the same refusal when their input is read elsewhere. Authored with Claude and Codex assistance. Differential Revision: D124032909 Pull Request resolved: #23773
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * __->__ #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 ET-VK's convolution reads and writes only channels-packed textures, but a convolution between linears could be given width-packed activations, so compile failed. The Vulkan engine converts a convolution's input and output to the layout the kernel needs. It refuses a transposed 1D convolution, which ET-VK would otherwise run as a forward one. Authored with Claude and Codex assistance. Differential Revision: D124032910 Pull Request resolved: #23774
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * __->__ #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 After a dynamic resize shrinks a conv1d's input, its texture is longer than the input, so padding taps read stale texels from an earlier, longer run and the last output frames were wrong. The conv1d shader reads zeros for taps outside the input's logical length. Authored with Claude and Codex assistance. cc @SS-JIA @manuelcandales @cbilgin Differential Revision: D124032911 Pull Request resolved: #23775
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…packed layout Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * __->__ #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 ET-VK's pad picks its shader by the output's layout alone, so when layout assignment gave its input another layout, as in pad -> reshape -> linear, results were silently wrong. Pad's input and output always share one packed layout, so pad is correct whatever layout layout assignment picks for either side. Authored with Claude and Codex assistance. Differential Revision: D124032912 Pull Request resolved: #23776
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…g, lt and conv1d Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * __->__ #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The ggml diffs above this one, and the speech encoders they serve, need ops the ggml engine did not lower. The ggml engine lowers layer norm over the last dim (F32 only), GELU in both forms, log, in-place sigmoid, zero constant padding, less-than and 1D convolution. It also accepts an attention mask with a single query row. The cross-engine tests that skipped ggml for these ops now run on both engines. Authored with Claude and Codex assistance. Differential Revision: D124165055 Pull Request resolved: #23777
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * __->__ #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 HuggingFace attention transposes q, k and v to head-major and back, and the ggml lowering copied every such permutation, adding copy kernels per attention layer on every step. Permutations of storage the graph never writes stay strided views. Ops that can read strides consume them directly, and any other reader gets one shared copy. Authored with Claude and Codex assistance. Differential Revision: D124020049 Pull Request resolved: #23778
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * __->__ #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 With an FP16 KV cache, the exported query is cast to F16 to match the cache, and the ggml lowering cast it back to F32 for attention, adding two copy kernels per attention. Attention reads the query's F32 source directly, which gives the same result because ggml's attention rounds the query itself. A source that could change before the read keeps its cast. Authored with Claude and Codex assistance. Differential Revision: D124020051 Pull Request resolved: #23779
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * #23781 * __->__ #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 A static-cache LLM attends its whole cache on every step, though the causal mask hides the keys past the current position, so most attention work at long contexts goes to masked keys. When an attention mask hides every key past the query positions, the ggml engine attends only the key prefix some query can see, and keeps replaying cached graphs as that prefix grows. Authored with Claude and Codex assistance. Differential Revision: D124020057 Pull Request resolved: #23780
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * #23782 * __->__ #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 Batch norm recomputed its scale and shift from constant statistics on every call, about seven ggml ops per norm. Batch norms with constant statistics fold to a precomputed scale and shift at load. A convolution whose output and weight nothing else reads absorbs its batch norm entirely. The PTN is unchanged. Authored with Claude and Codex assistance. Differential Revision: D124020059 Pull Request resolved: #23781
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * #23783 * __->__ #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 ggml's im2col can be inefficient for 1x1 convolutions on some backends; on Metal, for example, it runs one thread per threadgroup for a 1x1 kernel. 1x1 convolutions on the ggml engine no longer use per-tap im2col. Results are bit-identical, and larger kernels are unchanged. Authored with Claude and Codex assistance. Differential Revision: D124020060 Pull Request resolved: #23782
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
…on Metal Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * #23784 * __->__ #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The ggml engine could run on CPU, CUDA and HIP, but had no build for Apple GPUs through ggml's Metal backend. Adds build targets for ggml's Metal backend and an arm64 CPU backend, and Metal variants of the ggml engine and LLM runner. Authored with Claude and Codex assistance. Differential Revision: D124020061 Pull Request resolved: #23783
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * #23786 * __->__ #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 ggml has no integer arithmetic kernels, so an integer elementwise op, such as an int64 input plus a scalar, compiled and then aborted the ggml CPU runner. Integer elementwise arithmetic on the ggml engine runs in F32, which holds the engine's integer values exactly up to 2^24. Authored with Claude and Codex assistance. Differential Revision: D124165057 Pull Request resolved: #23784
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 14, 2026
Stack from [ghstack](https://github.com/ezyang/ghstack/tree/0.15.0) (oldest at bottom): * __->__ #23786 * #23784 * #23783 * #23782 * #23781 * #23780 * #23779 * #23778 * #23777 * #23776 * #23775 * #23774 * #23773 * #23772 * #23771 * #23770 * #23769 * #23768 * #23767 * #23766 * #23765 * #23764 * #23763 * #23762 * #23761 * #23760 * #23759 * #23758 * #23757 * #23756 * #23755 * #23754 * #23753 * #23752 * #23751 * #23750 * #23749 * #23748 * #23747 The ggml engine was one file of over 4,000 lines holding type handling, host-integer folding, the graph builder, every op lowering and the executable, so changes and reviews meant navigating all of it. Splits it into units for types, host integers, the graph builder and op families (elementwise, shape, linear, convolution, attention), with the executable left in `GgmlExecutor.cpp`. It is pure code motion with no behavior change. Authored with Claude and Codex assistance. Differential Revision: D124314780 Pull Request resolved: #23786
digantdesai
added a commit
that referenced
this pull request
Oct 14, 2026
…#23827) This PR was created by the merge bot to help merge the original PR into the main branch. ghstack PR number: #23752 by @digantdesai ^ Please use this as the source of truth for the PR details, comments, and reviews ghstack PR base: https://github.com/pytorch/executorch/tree/gh/digantdesai/143/base ghstack PR head: https://github.com/pytorch/executorch/tree/gh/digantdesai/143/head Merge bot PR base: https://github.com/pytorch/executorch/tree/gh/digantdesai/142/orig Merge bot PR head: https://github.com/pytorch/executorch/tree/gh/digantdesai/143/orig Differential Revision: [D123796919](https://our.internmc.facebook.com/intern/diff/D123796919/) @diff-train-skip-merge Co-authored-by: Digant Desai <digantdesai@meta.com>
This branch was successfully 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.
Stack from ghstack (oldest at bottom):
Check the ggml engine against eager PyTorch one operator at a time, so lowering bugs show up before they are buried in a model run.
Adds a small PTN runner, and an op test suite that runs one-op modules on the ggml engine and compares them with eager. It only includes cases that already pass; later fixes add their own.
Authored with Claude and Codex assistance.
Differential Revision: D123796919