Background
tt.spyre_tensor_layout (introduced in #74, "RewriteDescriptorLayout:
physicalize tensor descriptors for stick-tiled device layouts") lets a
Triton-Spyre kernel annotate a tensor descriptor with a physical coordinate
decomposition — three parallel arrays phys_src/phys_op/phys_arg
describing, per physical dim, which logical dim it derives from and whether
via identity, floordiv, or mod. This is the Triton-DSL analog of
TensorArg.device_coordinates in torch-spyre's OpSpec IR — it says where
each element physically lives.
What tt.spyre_tensor_layout does not express and what Triton's ordinary
tensor type system (tl.float16, tl.bfloat16, etc.) also does not express
is how elements are arranged/packed within a stick for certain hardware
conversions. torch-spyre tracks this separately as element_arrangement
(ElementArrangement enum: STANDARD, DL16_TO_FP32, FP32_TO_DL16,
QFP8CH, QFP8WT, EXX2) on SpyreTensorLayout/TensorArg. Certain
fp16/bf16↔fp32 hardware conversions produce a "staggered" physical layout,
elements interleaved/reordered within a stick rather than laid out in simple
row-major order, and this is orthogonal to dtype: it's about intra-stick
element ordering, not the element's storage format. A Triton kernel that
needs to consume or produce a staggered tensor currently has no way to
declare that.
Here is the example OpSpec using the element_arrangement field:
KERNEL_NAME = "sdsc_fused__to_copy_0"
POOL_SIZE = 0
BUNDLE_SYMBOLIC_ARGS = True
INPUTS_PT = os.path.splitext(os.path.abspath(__file__))[0] + ".inputs.pt"
# Host (shape, dtype) per kernel arg, in arg_index order.
SHAPES = [
([4, 128], torch.float16),
([4, 128], torch.float32)
]
# Exact device layout each arg had when the real graph ran.
LAYOUTS = [
SpyreTensorLayout(
device_size=[2, 4, 64],
stride_map=[64, 128, 1],
device_dtype=DataFormats.SEN169_FP16,
element_arrangement=ElementArrangement.STANDARD,
),
SpyreTensorLayout(
device_size=[4, 4, 32],
stride_map=[32, 128, 1],
device_dtype=DataFormats.IEEE_FP32,
element_arrangement=ElementArrangement.DL16_TO_FP32,
),
]
ops = [
OpSpec(
op='dl16tofp32',
is_reduction=False,
iteration_space={sympify('c0'): (sympify('4'), 4), sympify('c1'): (sympify('128'), 2)},
op_info={},
symbolic_dim_bounds={},
debug_handle=DebugHandle(id=4224585593578919848, source=SourceLoc(file='staggered_ea.py', start_line=6, start_col=0, end_line=None, end_col=None), aten_op='aten._to_copy.default', ir_chain=('convert_element_type', 'buf0'), fused_from=(), transform_history=()),
args=[
TensorArg(
is_input=True, arg_index=0, device_dtype=DataFormats.SEN169_FP16,
device_size=[2, 4, 64],
device_coordinates=[sympify('floor(c1/64)'), sympify('c0'), sympify('Mod(c1, 64)')],
allocation={'hbm': 0},
),
TensorArg(
is_input=False, arg_index=1, device_dtype=DataFormats.IEEE_FP32,
device_size=[4, 4, 32],
device_coordinates=[sympify('floor(c1/32)'), sympify('c0'), sympify('Mod(c1, 32)')],
allocation={'hbm': 1},
element_arrangement=ElementArrangement.DL16_TO_FP32,
),
]
),
]
Proposal
Extend tt.spyre_tensor_layout (and its tl.spyre_tensor_layout frontend
builtin) with an element_arrangement attribute, applying to the whole
descriptor (not per-dimension, since staggering is not a coordinate
operation like phys_src/phys_op/phys_arg):
tl.spyre_tensor_layout(desc, layout, element_arrangement="DL16_TO_FP32")
lowering to an element_arrangement attribute on tt.spyre_tensor_layout
alongside the existing phys_src/phys_op/phys_arg arrays. Defaults to
STANDARD/omitted when not specified, matching the "omit if default"
convention already used throughout torch-spyre's own OpSpec serialization
(torch_spyre/_inductor/spyre_kernel.py).
Why this matters
Without this, any Triton-Spyre kernel that touches a staggered fp16↔fp32
conversion has no way to describe that at the descriptor level — the
information exists in torch-spyre's OpSpec IR today but has no Triton-DSL
counterpart, making it impossible to hand-write or lower to a Triton kernel
that participates in one of these conversions without out-of-band knowledge.
References
cc. @fabianlim
Background
tt.spyre_tensor_layout(introduced in #74, "RewriteDescriptorLayout:physicalize tensor descriptors for stick-tiled device layouts") lets a
Triton-Spyre kernel annotate a tensor descriptor with a physical coordinate
decomposition — three parallel arrays
phys_src/phys_op/phys_argdescribing, per physical dim, which logical dim it derives from and whether
via identity,
floordiv, ormod. This is the Triton-DSL analog ofTensorArg.device_coordinatesin torch-spyre's OpSpec IR — it says whereeach element physically lives.
What
tt.spyre_tensor_layoutdoes not express and what Triton's ordinarytensor type system (
tl.float16,tl.bfloat16, etc.) also does not expressis how elements are arranged/packed within a stick for certain hardware
conversions. torch-spyre tracks this separately as
element_arrangement(
ElementArrangementenum:STANDARD,DL16_TO_FP32,FP32_TO_DL16,QFP8CH,QFP8WT,EXX2) onSpyreTensorLayout/TensorArg. Certainfp16/bf16↔fp32 hardware conversions produce a "staggered" physical layout,
elements interleaved/reordered within a stick rather than laid out in simple
row-major order, and this is orthogonal to dtype: it's about intra-stick
element ordering, not the element's storage format. A Triton kernel that
needs to consume or produce a staggered tensor currently has no way to
declare that.
Here is the example OpSpec using the
element_arrangementfield:Proposal
Extend
tt.spyre_tensor_layout(and itstl.spyre_tensor_layoutfrontendbuiltin) with an
element_arrangementattribute, applying to the wholedescriptor (not per-dimension, since staggering is not a coordinate
operation like
phys_src/phys_op/phys_arg):lowering to an
element_arrangementattribute ontt.spyre_tensor_layoutalongside the existing
phys_src/phys_op/phys_argarrays. Defaults toSTANDARD/omitted when not specified, matching the "omit if default"convention already used throughout torch-spyre's own OpSpec serialization
(
torch_spyre/_inductor/spyre_kernel.py).Why this matters
Without this, any Triton-Spyre kernel that touches a staggered fp16↔fp32
conversion has no way to describe that at the descriptor level — the
information exists in torch-spyre's OpSpec IR today but has no Triton-DSL
counterpart, making it impossible to hand-write or lower to a Triton kernel
that participates in one of these conversions without out-of-band knowledge.
References
tt.spyre_tensor_layout,tl.spyre_tensor_layout, andRewriteDescriptorLayout(the mechanism this issue extends)kernel[grid](...)reaches the backend #106 — example of currentLAYOUT=[...]usage in driver-launch fixturestorch_spyre/csrc/spyre_tensor_impl.h—ElementArrangementdefinitiontorch_spyre/_inductor/spyre_kernel.py— existing "omit if default"serialization convention this proposal mirrors
cc. @fabianlim