You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[ET-VK][runtime] Preserve zero padding in unary operators - #24754
Make buffer storage behave more like texture storage, so one shader can service
both storage types and buffer tensors need only a single vectorized shader.
Zero-valued padding lets later vectorized operators consume full vectors
without masking.
Rationale
What: Unary operators keep the padding of their outputs zero, and buffer
and texture tensors share one vectorized unary shader.
Why: Buffer tensors now pad their packed dim to four, like textures. If
every operator leaves that padding zero, consumers can load whole vec4s without
masking. Padding to four also makes buffer vec4 loads always in bounds, so the
per-element buffer shader is no longer needed.
Details
Unary shader
Before: buffers used a scalar path, one element per thread; textures
used a vec4 path. Neither kept padding zero.
After: one vec4 path for both. Buffers dispatch padded numel / 4
threads and index the buffer as vec4s. Math runs in texel_type (fp32 for
half). Ops that map zero to zero skip masking. Others zero padding lanes
when op(0) != 0 for the given bounds, e.g. clamp(0, 1, 2).
Input padding is assumed zero: an op that maps zero to zero keeps output
padding zero only if its input's padding is zero.
unary_op_preserves_zero(op_type) in unary_op.glslh lists the ops that
map zero to zero. Like apply_unary_op, it takes the op type as an
argument.
Dispatch
New default_pick_vec4_gwg in Common: one thread per output vec4.
Buffers get padded numel / 4 threads; textures keep the texel grid.
The output's hashed layout is passed as a spec constant. Input and output
must match in storage type and dtype. Buffers must also match in hashed
layout, since the shader reads and writes the same texel index; textures
need standard axis maps and matching packed dims.
Padding helpers in indexing.glslh
num_valid_lanes and mask_padding_lanes take a buffer texel index, a
texture position or a TensorIndex. When the packed dim needs no padding, mask_padding_lanes returns after one check that every thread evaluates
the same way.
After: suites can opt into a physical padding check. OutputPaddingCheck poisons the output's padding through an aliased padded
view before execution, then reads it back and checks it is zero, separately
from the logical comparison. A packed dim beyond the tensor's rank is
innermost in that view. Benchmark generation does not insert these checks.
suite.check_zero_padding=True
Enabled for the unary suites, the dedicated tan suite and GELU, which
now run width-, height- and channels-packed.
New padding-checked suites: relu, sigmoid, tanh and abs over
[-2, 2]; clamp and hardtanh with bounds on both sides of zero; clamp
with None bounds and int32 inputs; bitwise_not and logical_not on
bool.
Smaller changes:
Registering a second suite for an op adds to the first instead of replacing
it. The dedicated tan suite gets a name suffix.
Optional scalar arguments generate add_none() or a scalar value.
New test_generator Python unit test target.
New dynamic_clamp_zeroes_output_padding test: clamp with SymInt bounds
must zero output padding that was poisoned before execution.
Review unary.glsl, unary_op.glslh and indexing.glslh first, then UnaryOp.cpp and Common, then the test generator.
meta-claBot
added
the
CLA Signed
This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
label
Nov 6, 2026
If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.
To add a label, you can comment to pytorchbot, for example @pytorchbot label "release notes: none"
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
CLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exported
2 participants
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):
Ulterior Motive
Make buffer storage behave more like texture storage, so one shader can service
both storage types and buffer tensors need only a single vectorized shader.
Zero-valued padding lets later vectorized operators consume full vectors
without masking.
Rationale
What: Unary operators keep the padding of their outputs zero, and buffer
and texture tensors share one vectorized unary shader.
Why: Buffer tensors now pad their packed dim to four, like textures. If
every operator leaves that padding zero, consumers can load whole vec4s without
masking. Padding to four also makes buffer vec4 loads always in bounds, so the
per-element buffer shader is no longer needed.
Details
used a vec4 path. Neither kept padding zero.
threads and index the buffer as vec4s. Math runs in
texel_type(fp32 forhalf). Ops that map zero to zero skip masking. Others zero padding lanes
when
op(0) != 0for the given bounds, e.g.clamp(0, 1, 2).padding zero only if its input's padding is zero.
unary_op_preserves_zero(op_type)inunary_op.glslhlists the ops thatmap zero to zero. Like
apply_unary_op, it takes the op type as anargument.
default_pick_vec4_gwginCommon: one thread per output vec4.Buffers get padded numel / 4 threads; textures keep the texel grid.
must match in storage type and dtype. Buffers must also match in hashed
layout, since the shader reads and writes the same texel index; textures
need standard axis maps and matching packed dims.
indexing.glslhnum_valid_lanesandmask_padding_lanestake a buffer texel index, atexture position or a
TensorIndex. When the packed dim needs no padding,mask_padding_lanesreturns after one check that every thread evaluatesthe same way.
Before: generated tests compared logical outputs only.
After: suites can opt into a physical padding check.
OutputPaddingCheckpoisons the output's padding through an aliased paddedview before execution, then reads it back and checks it is zero, separately
from the logical comparison. A packed dim beyond the tensor's rank is
innermost in that view. Benchmark generation does not insert these checks.
Enabled for the unary suites, the dedicated
tansuite and GELU, whichnow run width-, height- and channels-packed.
New padding-checked suites:
relu,sigmoid,tanhandabsover[-2, 2];
clampandhardtanhwith bounds on both sides of zero;clampwith
Nonebounds and int32 inputs;bitwise_notandlogical_notonbool.
Smaller changes:
it. The dedicated
tansuite gets a name suffix.add_none()or a scalar value.test_generatorPython unit test target.dynamic_clamp_zeroes_output_paddingtest: clamp with SymInt boundsmust zero output padding that was poisoned before execution.
Review
unary.glsl,unary_op.glslhandindexing.glslhfirst, thenUnaryOp.cppandCommon, then the test generator.Authored with Codex and Claude Code.
Differential Revision: D130297303