Files
cutlass/python/CuTeDSL/cutlass/cute/nvgpu/warp/mma.py
T
Junkai-WuandLarry Wu b1d6e2c9b3 v4.3 update. (#2709)
* v4.3 update.

* Update the cute_dsl_api changelog's doc link

* Update version to 4.3.0

* Update the example link

* Update doc to encourage user to install DSL from requirements.txt

---------

Co-authored-by: Larry Wu <larwu@nvidia.com>
2025-10-21 14:26:30 -04:00

183 lines
6.1 KiB
Python

# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: LicenseRef-NvidiaProprietary
#
# Use of this software is governed by the terms and conditions of the
# NVIDIA End User License Agreement (EULA), available at:
# https://docs.nvidia.com/cutlass/media/docs/pythonDSL/license.html
#
# Any use, reproduction, disclosure, or distribution of this software
# and related documentation outside the scope permitted by the EULA
# is strictly prohibited.
from dataclasses import dataclass
from typing import Type
import enum
from cutlass import cute
from ..common import OpError
from ...typing import Shape, Float16, BFloat16, Float32, Numeric
from ...core import _pack_shape
from ...tensor import _Tensor
from ...atom import MmaOp, Trait
import cutlass._mlir.dialects.cute_nvgpu as _cute_nvgpu_ir
from cutlass._mlir.dialects.cute_nvgpu import SparseMetadataFormat
####################################################################################################
#
# MMA Ops and Traits
#
####################################################################################################
class WarpMmaOp(MmaOp):
"""
Base class for all warp-level MMA operations.
"""
pass
@dataclass(frozen=True)
class MmaF16BF16Op(WarpMmaOp):
"""
F16/BF16 tcgen05 MMA Operation.
See the `PTX documentation <https://docs.nvidia.com/cuda/parallel-thread-execution/#warp-level-matrix-instructions-mma>`__.
This Operation covers the instructions using the ``.f16`` or ``.bf16`` qualifiers for the input operands.
"""
ab_dtype: Type[Numeric]
acc_dtype: Type[Numeric]
shape_mnk: Shape
def __post_init__(self) -> None:
if self.ab_dtype not in [Float16, BFloat16]:
raise OpError(
self,
"expects the 'ab_dtype' Op parameter to be one of Float16 or BFloat16",
)
if self.acc_dtype not in [Float16, Float32]:
raise OpError(
self,
"expects the 'acc_dtype' Op parameter to be one of Float16 or Float32",
)
if (self.ab_dtype == BFloat16) and (self.acc_dtype != Float32):
raise OpError(
self,
"expects the 'acc_dtype' Op parameter to be Float32 when 'ab_dtype' is BFloat16",
)
if self.shape_mnk not in [(16, 8, 8), (16, 8, 16)]:
raise OpError(
self,
"expects the 'shape_mnk' Op parameter to be one of (16,8,8) or (16,8,16)",
)
def _make_trait(self, *, loc=None, ip=None, **kwargs) -> "MmaF16BF16Trait":
shape_mnk = _pack_shape(self.shape_mnk, loc=loc, ip=ip)
ty = _cute_nvgpu_ir.MmaAtomSM80Type.get(
shape_mnk.type.attribute,
self.ab_dtype.mlir_type,
self.ab_dtype.mlir_type,
self.acc_dtype.mlir_type,
)
return MmaF16BF16Trait(cute.make_atom(ty, loc=loc, ip=ip))
def __str__(self) -> str:
return (
"warp-level F16/BF16 MMA Operation"
+ f"\n A/B data type = {self.ab_dtype}"
+ f"\n Accumulator data type = {self.acc_dtype}"
+ f"\n Instruction shape MNK = {self.shape_mnk}"
)
def _verify_fragment_A(self, input: _Tensor, *, loc=None, ip=None):
pass
def _verify_fragment_B(self, input: _Tensor, *, loc=None, ip=None):
pass
class MmaF16BF16Trait(Trait):
pass
class SparseMetadataFormat(enum.Enum):
"""
An enumeration for the sparse metadata format of the MMA.
"""
TID = SparseMetadataFormat.tid
def __str__(self) -> str:
return f"{self.__class__.__name__}.{self.name}"
def __repr__(self) -> str:
return f"<{self.__class__.__name__}.{self.name}>"
def _to_ir(self) -> _cute_nvgpu_ir.SparseMetadataFormat:
return self.value
@dataclass(frozen=True)
class MmaF16BF16SparseOp(WarpMmaOp):
ab_dtype: Type[Numeric]
acc_dtype: Type[Numeric]
shape_mnk: Shape
sparse_metadata_format: SparseMetadataFormat
def __post_init__(self) -> None:
# verify field after initialization
if not isinstance(self.sparse_metadata_format, SparseMetadataFormat):
raise OpError(
self,
"expects the 'sparse_metadata_format' Op parameter to be a SparseMetadataFormat instance",
)
# verify the instruction shape
if self.ab_dtype not in [Float16, BFloat16]:
raise OpError(
self,
"expects the 'ab_dtype' Op parameter to be one of Float16 or BFloat16",
)
if self.acc_dtype not in [Float16, Float32]:
raise OpError(
self,
"expects the 'acc_dtype' Op parameter to be one of Float16 or Float32",
)
if (self.ab_dtype == BFloat16) and (self.acc_dtype != Float32):
raise OpError(
self,
"expects the 'acc_dtype' Op parameter to be Float32 when 'ab_dtype' is BFloat16",
)
if self.shape_mnk not in [(16, 8, 16), (16, 8, 32)]:
raise OpError(
self,
"expects the 'shape_mnk' Op parameter to be one of (16,8,16) or (16,8,32)",
)
def _make_trait(self, *, loc=None, ip=None, **kwargs) -> "MmaF16BF16SparseTrait":
shape_mnk = _pack_shape(self.shape_mnk, loc=loc, ip=ip)
ty = _cute_nvgpu_ir.MmaAtomSM80SparseType.get(
shape_mnk.type.attribute,
self.ab_dtype.mlir_type,
self.ab_dtype.mlir_type,
self.acc_dtype.mlir_type,
self.sparse_metadata_format._to_ir(),
)
return MmaF16BF16SparseTrait(cute.make_atom(ty, loc=loc, ip=ip))
def __str__(self) -> str:
return (
"warp-level F16/BF16 Sparse MMA Operation"
+ f"\n A/B data type = {self.ab_dtype}"
+ f"\n Accumulator data type = {self.acc_dtype}"
+ f"\n Instruction shape MNK = {self.shape_mnk}"
+ f"\n Sparse metadata format = {self.sparse_metadata_format}"
)
class MmaF16BF16SparseTrait(Trait):
pass