* 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>
183 lines
6.1 KiB
Python
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
|