Arguments and Operands#
An operation is expressed as a RuntimeArguments
object that describes both the operation kind (e.g. GEMM) and the operands it
runs on. Each operation has its own RuntimeArguments subclass. Operands are
described by Operand subclasses such as
DenseTensor and
ScaledOperand. Tensor- and numeric-typed fields
within Arguments and Operands accept any object matching the
TensorLike / NumericLike
protocols (e.g. torch.Tensor, cute.Tensor, cutlass.Numeric,
torch.dtype).
RuntimeArguments#
- class cutlass.operators.arguments.base.RuntimeArguments(
- *,
- performance: PerformanceControls | None = None,
Bases:
objectDescribes the operands and all other arguments passed to an Operator at runtime.
It contains runtime operands (usually tensors) passed to the operation, as well as any custom epilogue fusions, and runtime performance controls.
This is an abstract base class, whose subclass describes the operation type itself (e.g. GemmArguments, GroupedGemmArguments, etc.). All operators that implement the same operation type accept the same RuntimeArguments subclass.
- performance: PerformanceControls | None = None#
Optional runtime performance controls passed to the Operator
- class cutlass.operators.arguments.base.PerformanceControls#
Bases:
objectOptional runtime performance controls passed to the Operator.
Some operators may support performance options that can be controlled at runtime. This class is the general container for all such controls.
- class cutlass.operators.arguments.gemm.GemmProblemSize(M: int, N: int, K: int, L: int)#
Bases:
NamedTupleProblem size for a GEMM operation.
A GEMM with problem size (M, N, K, L) has operands with the following shapes (batch, rows, columns):
A: (L, M, K)B: (L, K, N)out: (L, M, N)
- M: int#
Number of rows in A and out
- N: int#
Number of columns in B and out
- K: int#
Number of columns in A and rows in B
- L: int#
Number of batches of matrix multiplications
- class cutlass.operators.arguments.gemm.GemmArguments(
- A: TensorLike | Operand,
- B: TensorLike | Operand,
- out: TensorLike | Operand,
- accumulator_type: NumericLike,
- epilogue: EpilogueArguments | None = None,
Bases:
RuntimeArgumentsArguments for a Generalized Matrix Multiplication (GEMM) operation:
out = A @ B.The tensors must be all rank-3 or all rank-2. *
L: Number of batches *M: Number of rows in A and out *K: Number of columns in A and rows in B *N: Number of columns in B and outFor convenience, construction for
A,B, andoutthat are operands to a dense GEMM can be passed in without wrapping them inDenseTensor.GemmArguments(A, B, out, accumulator_type) # is equivalent to: GemmArguments(DenseTensor(A), DenseTensor(B), DenseTensor(out), accumulator_type)
Other operand types must explicitly wrap tensors in a
Operandsubclass. For example, a scaled GEMM can be constructed as:GemmArguments( ScaledOperand(A, ScaleATensor, scale_mode, scale_swizzle), ScaledOperand(B, ScaleBTensor, scale_mode, scale_swizzle), out, # No need to wrap in a `DenseTensor` accumulator_type, )
- accumulator_type: NumericLike#
Data type of the accumulator
- epilogue: EpilogueArguments | None#
Optional custom epilogue fusion to be performed after the GEMM
- property problem_size: GemmProblemSize#
Problem size for a GEMM operation.
- class cutlass.operators.arguments.grouped_gemm.GroupedGemmArguments(
- A: TensorLike | Operand,
- B: TensorLike | Operand,
- out: TensorLike | Operand,
- accumulator_type: NumericLike,
- offsets: TensorLike | Operand,
- epilogue: EpilogueArguments | None = None,
Bases:
RuntimeArgumentsArguments for a grouped GEMM operation.
A grouped GEMM performs a series of independent GEMM operations, where each GEMM can have different matrix dimensions. The most basic formulation of a grouped GEMM is one that takes lists of tensors for each of
A,B, andout, and computes the following:for i in range(problems_in_group): out[i] = A[i] @ B[i]
While the abstract formulation uses lists of tensors, in practice, the tensors are often packed together contiguously in memory in a single tensor for each of
A,B, andout. In this case, anoffsetstensor delineates the ending positions of each problem in the group within those contiguous tensors.Currently-supported variants of a grouped GEMM are:
- Contiguous offset 2D-3D grouped GEMM:
Ais a tensor of shape (TotalM, K) or (1, TotalM, K)Bis a tensor of shape (problems_in_group, K, N)outis a tensor of shape (TotalM, N) or (1, TotalM, N)offsetsis a tensor delineating the ending positions of each problem in the group.
start = 0 for i in range(problems_in_group): end = offsets[i] out[start:end, :] = A[start:end, :] @ B[i, :, :] start = end
- accumulator_type: NumericLike#
Data type of the accumulator
- epilogue: EpilogueArguments | None#
Optional custom epilogue fusion to be performed after the GEMM
- class cutlass.operators.arguments.epilogue.EpilogueArguments(epilogue_fn: Callable | str, **kwargs)#
Bases:
objectDescribes a user-defined epilogue that is fused on top of the operation described by the primary RuntimeArguments.
An epilogue fusion is a custom function that performs tensor-level transformations on the result of a matrix multiplication. This transformation is fused into the kernel’s epilogue, which stores the final output.
EpilogueArgumentsencapsulates the epilogue function describing the transformation along with its arguments.To support flexible definition of epilogues,
EpilogueArgumentsis defined generically as taking in anepilogue_fnand additionalkwargs.Under the hood, the AST for
epilogue_fnis parsed to determine the operands and outputs of the epilogue.kwargsmust contain Tensors or scalars for all operands and outputs in the provided epilogue.Structure of ``epilogue_fn``
The
epilogue_fnis a function describing the custom transformation on the accumulator tensor (intermediate result before the epilogue).The general structure of these functions is:
def custom_epi_name(accum, *args) -> TensorType | tuple[TensorType, ...]: '''Compute the epilogue. # Args: accum (TensorType): Result of the primary operation (e.g. ``A @ B`` for a GEMM) before the epilogue. *args: Additional tensors or scalars used in the epilogue (e.g. aux tensors). # Returns: At least one tensor resulting from the epilogue computation. ''' # Do some compute return D # and potentially other values
epilogue_fnmust be a Python callable (or its string representation) that must satisfy the following constraints:Takes a first positional argument named
accum– the result of the operation just before the epilogue. For a GEMM,accum = A @ B.Returns at least one tensor resulting from the epilogue. Currently the return list must contain at least one output named
D.Each argument following
accumis a tensor or scalar to be loaded.Each variable in the return statement is a tensor or scalar to be stored.
Operations are represented in static single assignment (SSA) form. This means that each variable can be assigned exactly once.
The underlying implementation of the epilogue in the kernel will determine how operands are loaded and stored.
Structure of ``kwargs``
kwargsmust contain sample Tensors or scalars for all operands and outputs in the provided epilogue. For example, with an epilogue of:def my_epi(accum, alpha, C, beta): F = (accum * alpha) + (C * beta) D = relu(F) return D, F
A user would need to construct epilogue arguments as follows:
epi_args = EpilogueArguments( my_epi, alpha=..., C=..., beta=..., D=..., F=... )
- property parameters: list[cute.Tensor | Numeric]#
Returns the list of input and output parameters of the epilogue.
- property parameter_names: list[str]#
Returns the list of names of the input and output parameters of the epilogue.
- to_tensor_wrappers(permute: list[int] | None = None)#
Converts the input and output parameters of the epilogue to TensorWrappers.
- trace(
- accumulator_shape: tuple[int, ...],
- accumulator_type: Numeric,
Traces the epilogue function and generates an internal representation of the epilogue.
- Parameters:
accumulator_shape (tuple[int, ...]) – The shape of the accumulator tensor. For example, for a GEMM, this would be the shape of the output tensor.
accumulator_type (Numeric) – The datatype of the accumulator tensor.
Operands#
- class cutlass.operators.arguments.base.Operand#
Bases:
ABCBase class for all operands to Operators, which encapsulates one or more TensorLike objects.
In the most basic case, an Operand enacapsulates a single tensor.
In more complex cases, an Operand may encapsulate multiple tensors that encapsulate a single logical operand. For instance, a
ScaledOperandencapsulates a quantized and scale tensor, that together reconstruct the logical value of the operand.
- class cutlass.operators.arguments.operand.DenseTensor(tensor: cutlass.operators.typing.TensorLike)#
Bases:
OperandAn operand encapsulating a simple, single dense tensor.
- class cutlass.operators.arguments.operand.ScaledOperand(
- quantized: TensorLike | DenseTensor,
- scale: TensorLike | DenseTensor,
- mode: ScaleMode | tuple[int, ...],
- swizzle: ScaleSwizzleMode,
Bases:
OperandAn operand whose logical value is a quantized tensor multiplied by a tensor of scale factors.
A
ScaledOperandencapsulates physicalquantizedandscaletensors that together represent the logical valuescale * quantized: each entry ofscalebroadcasts and multiplies a contiguous block ofquantized, where the block shape is given bymode.This Operand is typically used to express narrow-precision formats (such as OCP MXFP8 / MXFP4 and NVIDIA NVFP4), which store the data as a quantized narrow-precision tensor multiplied by a separate tensor of scale factors that recover dynamic range.
The scale
modeandswizzledescribe the physical layout of the scale tensor.The
modedescribes how scale factors are broadcast over the quantized tensor, and therefore determines its size. It’s usually dictated by the data format you seek to represent – MXFP8 / MXFP4 / NVFP4 require specific scale modes. SeeScaleModefor more details.The
swizzledescribes the in-memory layout of the scale tensor. It’s usually dictated by the hardware architecture – for example, Blackwell block-scaled MMAs require a specific swizzle layout, and most kernels using them require the input to be pre-arranged in this layout. SeeScaleSwizzleModefor more details.Example
quantized_A = torch.randn(M, K, dtype=torch.float8_e4m3fn, device="cuda") scale_A = torch.randn(M, K // 32, dtype=torch.float8_e8m0fnu, device="cuda") A = ScaledOperand( quantized_A, scale_A, ScaleMode.Blockwise1x32, ScaleSwizzleMode.Swizzle32x4x4, )
See also
ScaleMode: granularity of the scaling, and the format-to-mode mapping.ScaleSwizzleMode: in-memory layout of the scale tensor.
References
- quantized: DenseTensor#
Narrow-precision tensor holding the quantized values.
The dequantized logical value is
scale * quantized: each scale factor broadcasts over a block of this tensor (block shape given bymode) and multiplies its values.
- scale: DenseTensor#
Tensor of scale factors.
Each entry of this tensor broadcasts over a block of
quantizedand scales it. Its shape and layout are determined together bymodeandswizzle.This tensor must be contiguous and have exactly
ScaledOperand.numel_scale()(quantized_shape, mode, swizzle)elements. It must already be arranged in the layout named byswizzle. Its shape is otherwise unconstrained and not validated.
- mode: ScaleMode | tuple[int, ...]#
Block shape over which each scale factor is broadcast.
Typically, a block of quantized-tensor elements share the same scale factor value. The logical value of the scaled operand is the result of broadcasting the scale factor along the block shape described by
mode, and then multiplying it element-wise with the quantized tensor.This may be a
ScaleModeenum for commonly used block shapes, or a bare(L, M, K)tuple for custom block shapes. For instance,(1, 1, 32)means that each scale factor covers 32 elements along the K axis, and 1 element along the L and M axes.
- swizzle: ScaleSwizzleMode#
In-memory layout of the scale factor tensor.
The scale factor tensor is sometimes required to be stored in a specific swizzled layout, often dictated by the hardware MMA’s contract.
- static numel_scale(
- quantized_shape: tuple[int, ...],
- mode: ScaleMode | tuple[int, ...],
- swizzle: ScaleSwizzleMode,
Return the number of elements expected in
scalefor an operand ofquantized_shape.quantized_shapeis(L, outer, K)for a 3D operand, whereouterisMfor an A-side scale andNfor a B-side scale. One scale factor coversVelements alongK, so the scale tensor has logical shape(L, outer, ceil_div(K, V)).scale.numel() must equal the value returned by this method. The shape of the scale tensor is otherwise unconstrained.
Returned value depends on
swizzle:ScaleSwizzleMode.SwizzleNone:L * outer * ceil_div(K, V)ScaleSwizzleMode.Swizzle32x4x4:L * round_up(outer, 128) * round_up(ceil_div(K, V), 4)
where
V = ScaleMode.numel(mode)is the number of quantized-tensor elements covered by one scale factor.- Parameters:
quantized_shape (tuple[int, ...]) – Logical shape of the operand the scale will be paired with, as
(L, outer, K)or(outer, K).mode (ScaleMode | tuple[int, ...]) – Block shape of the scaling.
swizzle (ScaleSwizzleMode) – In-memory layout of the scale tensor.
- Returns:
Required number of scale-factor elements.
- Return type:
int
- Raises:
ValueError – If
quantized_shapeis not rank 2 or 3, orswizzleis not a recognisedScaleSwizzleMode.
- class cutlass.operators.arguments.operand.ScaleMode(value)#
Bases:
EnumAn enum over commonly used block scaling modes for a
ScaledOperand.Each member’s value is a
(batch, row, col)tuple giving the shape of the block of quantized-tensor elements that share a scale factor. Each scale factor is broadcast & multiplied over this block of quantized-tensor elements.For block shapes that are not enumerated here, bare
(batch, row, col)tuples are also accepted asScaledOperand.modeSee also
ScaledOperand: the operand that consumes this enum.ScaleSwizzleMode: in-memory layout of the scale tensor.
- Blockwise1x16 = (1, 1, 16)#
Scale over
(1, 1, 16)block. Used by NVIDIA NVFP4 (FP8 E4M3 scale dtype).
- Blockwise1x32 = (1, 1, 32)#
Scale over
(1, 1, 32)block. Used by OCP MXFP8 / MXFP4 (E8M0 scale dtype).
- static compare( ) bool#
Return whether two scale modes describe the same scaling.
Allows mixed comparisons between
ScaleModeenums and bare tuples, and tolerates differing tuple lengths as long as the longer tuple has leading1s for the extra positions (so that, e.g.,(1, 1, 16) == (1, 16)).
- static numel(
- scale: ScaleMode | tuple[int, ...],
Return the number of quantized-tensor elements scaled by one scale factor.
For a scale mode of block shape
(L, M, K), this is the block volumeL * M * K– the number of contiguous elements in a quantized tensor that share (and are multiplied by) the same scale factor.- Parameters:
scale (ScaleMode | tuple[int, ...]) – Scale mode whose tuple entries give the block shape.
- Returns:
Product of the entries of
scale(e.g.numel(Blockwise1x32) == 32).- Return type:
int
- class cutlass.operators.arguments.operand.ScaleSwizzleMode(value)#
Bases:
EnumIn-memory layout of the scale tensor in a
ScaledOperand.Hardware MMAs that consume block-scaled inputs typically require their scale tensors to be stored in a specific non-trivial layout.
ScaleSwizzleModeindicates that scale factors inside aScaledOperandare already stored in one of those specific layouts.Operator API validates that the scale tensor is contiguous and has the element count required by
(mode, swizzle), but it does not inspect or rearrange the values. The producer of the scale tensor (typically a quantizer) is responsible for writing values in the named layout.See also
ScaledOperand: the operand that consumes this enum.ScaleMode: granularity of the scaling.PyTorch
torch.nn.functional.SwizzleType, which this enum closely resembles.
- SwizzleNone = 1#
Scale tensor stored in the natural ordering implied by
ScaleMode.For an
(L, M, K)operand at mode(1, 1, V), this is a tensor ofL * M * (K // V)scale factors with one value permodeblock.
- Swizzle32x4x4 = 2#
1D block-scaling layout dictated by Blackwell
tcgen05.mmablock-scaled MMAs.This is used for MXFP8 / MXFP4 / NVFP4 GEMMs on Blackwell. Under this layout, each tile contains 128x4 scale factors, and the 128 rows are interleaved in groups of 32, matching the warp-group structure of the Blackwell tensor core.
For a quantized tensor of shape
(L, M, K)and a scale vector size of V, the scale tensor is required to haveL * round_up(M, 128) * round_up(ceil_div(K, V), 4)elements.References
Type markers#
Type markers for CUTLASS Operator API field annotations.
- cutlass.operators.typing.TensorLike#
Tensor-like inputs accepted by the Operator API.
- Includes:
Any DLPack-compatible tensor (
torch.Tensor,jax.Array,numpy.ndarray, …).cutlass.cute.Tensor(CuTe DSL host tensor; does not implement DLPack but is handled natively byTensorWrapper).cutlass.operators.utils.tensor.TensorWrapper(implements DLPack).
alias of
_SupportsDLPack|Tensor|TensorWrapper
- class cutlass.operators.typing.NumericLike(*args, **kwargs)#
Bases:
ProtocolType marker for fields that accept numeric-like types.
- Fields annotated with NumericLike accept the following:
cutlass.Numerictorch.dtype