Repository navigation
Add optimized embedding_bag kernel (#24851) - #24851
JakeStevens wants to merge 1 commit into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24851
Note: Links to docs will display an error until the docs builds have been completed. ✅ You can merge normally! (4 Unrelated Failures)As of commit 47dbaba with merge base a70d32f ( BROKEN TRUNK - The following jobs failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@JakeStevens has exported this pull request. If you are a Meta employee, you can view the originating Diff in D123412521. |
Summary: Add an optimized `_embedding_bag.out` with FP32 weights, int32/int64 indices and offsets, sum/mean/max reductions, padding, per-sample weights for sum, and all four functional outputs. The kernel takes default-dim-order FP32 weights and outputs, with the index outputs typed like offsets as export allocates them, and falls back to the portable kernel for anything else. Bags are split across the threadpool. Sum and mean accumulate rows with `at::vec` across embedding dimensions, handling scalar tails; max is a scalar loop that preserves ATen's first-winner indices and NaN behavior. The kernel matches ATen's contiguous FP32 handling of a final offset below `indices.numel()`. No temporary tensor allocation is required. Profiling: warm FP32 sum, 4096 × 128 weight table, 256 bags × 32 indices. The 1-thread gain compares optimized with the single-threaded portable kernel; scaling compares the optimized kernel at 1 and 4 threads. These are kernel-call measurements, not end-to-end model latency. | Surface | 1-thread gain vs portable | Optimized 1→4-thread scaling | |---|---:|---:| | x86 · AMD EPYC | 7.54× | 3.04× | | Mac · Apple Silicon | 4.14× | 2.35× | | iPhone 17 | 5.90× | 1.58× | | Pixel 10 | 4.90× | No benefit established | Pixel 10 had measurement issues, with both baseline and test arm fluctuating. Authored with AI assistance using Codex and Claude Code. Differential Revision: D123412521
c4d9466 to
dc4d3fb
Compare
|
@claude review effort:max |
|
Claude finished @JakeStevens's task in 5m 38s —— View job I found no blockers or correctness bugs; the remaining issues are minor (logic copied from the portable kernel, gaps in test coverage, and some small performance and docs items), so I recommend Approve. Detailed reviewPR Review: #24851SummaryThis PR adds an optimized FP32
There are no thread-safety problems: workers only write bag-disjoint ranges, because offsets are validated as nondecreasing. All findings below are minor. Nothing was built or run; everything comes from reading the code. Code Quality
Testing
Performance
RecommendationApprove Nothing blocks merging. The two worth addressing before landing are the validate-before-resize ordering and the weighted-sum and multi-task test gaps. The rest are optional cleanups. |
Summary: Add an optimized `_embedding_bag.out` with FP32 weights, int32/int64 indices and offsets, sum/mean/max reductions, padding, per-sample weights for sum, and all four functional outputs. The CPU provider now routes `_embedding_bag.default` to the linked `_embedding_bag.out`, which works with the portable kernel too. Validation and output resizing move into a new shared `kernels/portable/cpu/util/embedding_bag_util.cpp`, which the portable kernel now also uses. The kernel takes default-dim-order FP32 weights and outputs, with the index outputs typed like offsets as export allocates them, and falls back to the portable kernel for anything else. Bags are split across the threadpool. Sum and mean accumulate rows with `at::vec` over whole vectors and a scalar loop for each row's remainder; max is a scalar loop that preserves ATen's first-winner indices and NaN behavior. The kernel matches ATen's contiguous FP32 handling of a final offset below `indices.numel()`. No temporary tensor allocation is required. Profiling: warm FP32 sum, 4096 × 128 weight table, 256 bags × 32 indices. The 1-thread gain compares optimized with the single-threaded portable kernel; scaling compares the optimized kernel at 1 and 4 threads. These are kernel-call measurements, not end-to-end model latency. | Surface | 1-thread gain vs portable | Optimized 1→4-thread scaling | |---|---:|---:| | x86 · AMD EPYC | 7.54× | 3.04× | | Mac · Apple Silicon | 4.14× | 2.35× | | iPhone 17 | 5.90× | 1.58× | | Pixel 10 | 4.90× | No benefit established | Pixel 10 had measurement issues, with both baseline and test arm fluctuating. Authored with AI assistance using Codex and Claude Code. Differential Revision: D123412521
dc4d3fb to
47dbaba
Compare
|
@claude review effort=max |
|
Claude encountered an error after 3m 16s —— View job I'll analyze this and get back to you. |
Summary:
Add an optimized
_embedding_bag.outwith FP32 weights, int32/int64 indices and offsets, sum/mean/max reductions, padding, per-sample weights for sum, and all four functional outputs. The CPU provider now routes_embedding_bag.defaultto the linked_embedding_bag.out, which works with the portable kernel too.Validation and output resizing move into a new shared
kernels/portable/cpu/util/embedding_bag_util.cpp, which the portable kernel now also uses. The kernel takes default-dim-order FP32 weights and outputs, with the index outputs typed like offsets as export allocates them, and falls back to the portable kernel for anything else. Bags are split across the threadpool. Sum and mean accumulate rows withat::vecover whole vectors and a scalar loop for each row's remainder; max is a scalar loop that preserves ATen's first-winner indices and NaN behavior. The kernel matches ATen's contiguous FP32 handling of a final offset belowindices.numel(). No temporary tensor allocation is required.Profiling: warm FP32 sum, 4096 × 128 weight table, 256 bags × 32 indices. The 1-thread gain compares optimized with the single-threaded portable kernel; scaling compares the optimized kernel at 1 and 4 threads. These are kernel-call measurements, not end-to-end model latency.
Pixel 10 had measurement issues, with both baseline and test arm fluctuating.
Authored with AI assistance using Codex and Claude Code.
Differential Revision: D123412521