v3.8.0 update (#2082)
* 3.8 update * fix Markus' name --------- Co-authored-by: yuzhai <yuzhai@nvidia.com>
This commit is contained in:
@@ -171,20 +171,6 @@ cooperative_gemm_predication(ThrMMA<Args...> const& thr_mma,
|
||||
// Create register tensors for the MMA to operate on
|
||||
Tensor tCrA = thr_mma.make_fragment_A(tCsA); // (MMA,MMA_M,MMA_K)
|
||||
Tensor tCrB = thr_mma.make_fragment_B(tCsB); // (MMA,MMA_N,MMA_K)
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print(" sA: "); print( sA); print("\n");
|
||||
print(" sB: "); print( sB); print("\n");
|
||||
print(thr_mma);
|
||||
print("tCsA: "); print(tCsA); print("\n");
|
||||
print("tCsB: "); print(tCsB); print("\n");
|
||||
print("tCrA: "); print(tCrA); print("\n");
|
||||
print("tCrB: "); print(tCrB); print("\n");
|
||||
print("tCrC: "); print(tCrC); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// PREDICATION
|
||||
//
|
||||
@@ -200,7 +186,6 @@ cooperative_gemm_predication(ThrMMA<Args...> const& thr_mma,
|
||||
// Allocate the preds for MMA- and MMA_MN-modes
|
||||
Tensor tCpA = make_tensor<bool>(make_shape(size<0>(tCsA), size<1>(tCsA)));
|
||||
Tensor tCpB = make_tensor<bool>(make_shape(size<0>(tCsB), size<1>(tCsB)));
|
||||
|
||||
// Populate the predicates on M and N
|
||||
CUTE_UNROLL
|
||||
for (int i = 0; i < size(tCpA); ++i) {
|
||||
@@ -210,18 +195,6 @@ cooperative_gemm_predication(ThrMMA<Args...> const& thr_mma,
|
||||
for (int i = 0; i < size(tCpB); ++i) {
|
||||
tCpB(i) = elem_less(get<0>(tCcB(_,_,Int<0>{})(i)), shape<0>(sB));
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print(" cA: "); print( cA); print("\n");
|
||||
print(" cB: "); print( cB); print("\n");
|
||||
print("tCcA: "); print(tCcA); print("\n");
|
||||
print("tCcB: "); print(tCcB); print("\n");
|
||||
print_tensor(tCpA);
|
||||
print_tensor(tCpB);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// PREFETCH k_block = 0
|
||||
// Condition the k-predication on (static) k_block == K_BLOCK_MAX-1, the last k_block
|
||||
@@ -330,24 +303,6 @@ cooperative_gemm_no_predication(uint32_t thread_idx,
|
||||
Tensor tCrBi_copy_view = smem_thr_copy_B.retile_D(tCrBi);
|
||||
CUTE_STATIC_ASSERT_V(size<1>(tCsB) == size<1>(tCrBi_copy_view)); // CPY_N
|
||||
CUTE_STATIC_ASSERT_V(size<2>(tCsB) == size<2>(tCrBi_copy_view)); // CPY_K
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print(" sA: "); print(sA); print("\n");
|
||||
print(" sB: "); print(sB); print("\n");
|
||||
print(thr_mma); print("\n");
|
||||
print("tCrA: "); print(tCrA); print("\n");
|
||||
print("tCrB: "); print(tCrB); print("\n");
|
||||
print("tCrC: "); print(tCrC); print("\n");
|
||||
print(smem_thr_copy_A); print("\n");
|
||||
print("tCsA: "); print(tCsA); print("\n");
|
||||
print("tCrA_copy_view: "); print(tCrA_copy_view); print("\n");
|
||||
print(smem_thr_copy_B); print("\n");
|
||||
print("tCsB: "); print(tCsB); print("\n");
|
||||
print("tCrB_copy_view: "); print(tCrB_copy_view); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// PREFETCH
|
||||
//
|
||||
@@ -434,14 +389,6 @@ cooperative_gemm(uint32_t thread_idx,
|
||||
|
||||
// Clear accumulators
|
||||
clear(tCrC);
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print(" sC: "); print(sC); print("\n");
|
||||
print(" tCsC: "); print(tCsC); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if constexpr (is_constant<true, decltype(compat)>::value) {
|
||||
detail::cooperative_gemm_no_predication(
|
||||
thread_idx, thr_mma, sA, sB, tCrC, sA_load_op, sB_load_op, sA_copy_op, sB_copy_op
|
||||
|
||||
@@ -248,15 +248,6 @@ copy(AutoVectorizingCopyWithAssumedAlignment<MaxVecBits> const&,
|
||||
// Recast
|
||||
Tensor src_v = recast<SrcVecType>(src);
|
||||
Tensor dst_v = recast<DstVecType>(dst);
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print("copy -- found max_common_vector of %d elems and vectorization to %d bits\n", common_elem, vec_bits);
|
||||
print(" "); print(src); print(" => "); print(src_v); print("\n");
|
||||
print(" "); print(dst); print(" => "); print(dst_v); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return copy_if(TrivialPredTensor{}, src_v, dst_v);
|
||||
} else {
|
||||
return copy_if(TrivialPredTensor{}, src, dst);
|
||||
@@ -374,15 +365,6 @@ copy(Copy_Traits<SM90_BULK_COPY_AUTO, CT_Args...> const& atom, // Copy_Traits m
|
||||
// Construct a new concrete Atom of the vector size
|
||||
using BulkAtom = Copy_Atom<Copy_Traits<BULK_COPY_OP, Int<vec_bits>, CT_Args...>, SrcType>;
|
||||
auto bulk_atom = apply(atom.opargs_, [](auto const&... args) { return BulkAtom{args...}; });
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print("copy blkcp -- found a max_common_layout of "); print(tiler); print("\n");
|
||||
print(" "); print(src); print("\n");
|
||||
print(" "); print(dst); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return copy(bulk_atom, logical_divide(src, tiler), logical_divide(dst, tiler));
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
# define CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED
|
||||
# define CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED
|
||||
# define CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED
|
||||
# define CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED
|
||||
#endif
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM100A_ENABLED)
|
||||
|
||||
@@ -219,7 +219,7 @@ to_CUtensorMapDataType() {
|
||||
if constexpr (is_same_v<T, double>) { return CU_TENSOR_MAP_DATA_TYPE_FLOAT64; } else
|
||||
if constexpr (is_same_v<T, bfloat16_t>) { return CU_TENSOR_MAP_DATA_TYPE_BFLOAT16; } else
|
||||
if constexpr (is_same_v<T, tfloat32_t>) { return CU_TENSOR_MAP_DATA_TYPE_TFLOAT32; } else
|
||||
#if defined(CUDA_VERSION) && CUDA_VERSION > 12060
|
||||
#if ((__CUDACC_VER_MAJOR__ > 12) || ((__CUDACC_VER_MAJOR__ == 12) && (__CUDACC_VER_MINOR__ > 6)))
|
||||
if constexpr (is_same_v<T, float_e2m3_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U6_ALIGN16B;} else
|
||||
if constexpr (is_same_v<T, float_e3m2_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U6_ALIGN16B;} else
|
||||
if constexpr (is_same_v<T, float_e2m1_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U4_ALIGN8B;} else
|
||||
@@ -231,6 +231,7 @@ to_CUtensorMapDataType() {
|
||||
if constexpr (is_same_v<T, detail::type_erased_dynamic_float4_unpacksmem_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U4_ALIGN16B;} else
|
||||
if constexpr (is_same_v<T, type_erased_dynamic_float4_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U4_ALIGN8B; } else
|
||||
#endif
|
||||
|
||||
{ static_assert(sizeof(T) < 0, "Unknown TMA Format!"); }
|
||||
}
|
||||
|
||||
@@ -247,23 +248,17 @@ to_CUtensorMapSwizzle(SmemSwizzleBits const& t, SmemSwizzleBase const& b) {
|
||||
case SmemSwizzleBits::B64:
|
||||
assert((b == SmemSwizzleBase::SWIZZLE_BASE_16B) && "Expected 16B swizzle base for 64B swizzle bits.");
|
||||
return CU_TENSOR_MAP_SWIZZLE_64B;
|
||||
#if (0)
|
||||
case SmemSwizzleBits::B128:
|
||||
assert((b == SmemSwizzleBase::SWIZZLE_BASE_16B) && "Expected 16B swizzle base for 128B swizzle bits.");
|
||||
return CU_TENSOR_MAP_SWIZZLE_128B;
|
||||
|
||||
#else
|
||||
case SmemSwizzleBits::B128:
|
||||
switch (b) {
|
||||
default: assert(false && "Unsupported pair of SmemSwizzleBits and SmemSwizzleBase!");
|
||||
case SmemSwizzleBase::SWIZZLE_BASE_16B: return CU_TENSOR_MAP_SWIZZLE_128B;
|
||||
#if defined(CUDA_VERSION) && CUDA_VERSION > 12060
|
||||
|
||||
#if ((__CUDACC_VER_MAJOR__ > 12) || ((__CUDACC_VER_MAJOR__ == 12) && (__CUDACC_VER_MINOR__ > 6)))
|
||||
case SmemSwizzleBase::SWIZZLE_BASE_32B: return CU_TENSOR_MAP_SWIZZLE_128B_ATOM_32B;
|
||||
case SmemSwizzleBase::SWIZZLE_BASE_64B: return CU_TENSOR_MAP_SWIZZLE_128B_ATOM_64B;
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -391,7 +391,6 @@ CUTE_HOST_DEVICE constexpr auto to_UMMAFormat() {
|
||||
|
||||
if constexpr (is_same_v<T, float_e4m3_t>) { return MXF8F6F4Format::E4M3; } else
|
||||
if constexpr (is_same_v<T, float_e5m2_t>) { return MXF8F6F4Format::E5M2; } else
|
||||
|
||||
if constexpr (is_same_v<T, detail::type_erased_dynamic_float6_unpacksmem_t>) {return MXF8F6F4Format::INVALID; } else
|
||||
if constexpr (is_same_v<T, detail::float_e2m3_unpacksmem_t>) { return MXF8F6F4Format::E2M3; } else
|
||||
if constexpr (is_same_v<T, detail::float_e3m2_unpacksmem_t>) { return MXF8F6F4Format::E3M2; } else
|
||||
@@ -399,7 +398,6 @@ CUTE_HOST_DEVICE constexpr auto to_UMMAFormat() {
|
||||
if constexpr (is_same_v<T, float_e3m2_t>) { return MXF8F6F4Format::E3M2; } else
|
||||
if constexpr (is_same_v<T, detail::float_e2m1_unpacksmem_t>) { return MXF8F6F4Format::E2M1; } else
|
||||
if constexpr (is_same_v<T, float_e2m1_t>) { return MXF4Format::E2M1; } else
|
||||
|
||||
{ static_assert(sizeof(T) == 0, "Unknown type for UMMAFormat"); }
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,10 @@ template <class a_type, class b_type, class c_type,
|
||||
struct SM100_MMA_TF32_SS
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_TF32 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_TF32 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
|
||||
(M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
|
||||
"SM100_MMA_TF32 N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
|
||||
or a multiple of 16 between 16 and 256 for M=128.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -64,17 +67,6 @@ struct SM100_MMA_TF32_SS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -99,7 +91,10 @@ template <class a_type, class b_type, class c_type,
|
||||
struct SM100_MMA_F16BF16_SS
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_F16BF16 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
|
||||
(M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
|
||||
"SM100_MMA_F16BF16 N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
|
||||
or a multiple of 16 between 16 and 256 for M=128.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -114,17 +109,6 @@ struct SM100_MMA_F16BF16_SS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -150,7 +134,10 @@ template <class a_type, class b_type, class c_type,
|
||||
struct SM100_MMA_TF32_TS
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_TF32 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_TF32 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
|
||||
(M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
|
||||
"SM100_MMA_TF32 N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
|
||||
or a multiple of 16 between 16 and 256 for M=128.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_TF32 A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
@@ -166,16 +153,6 @@ struct SM100_MMA_TF32_TS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_a);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
if (cute::elect_one_sync()) {
|
||||
asm volatile(
|
||||
@@ -201,7 +178,10 @@ template <class a_type, class b_type, class c_type,
|
||||
struct SM100_MMA_F16BF16_TS
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_F16BF16 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
|
||||
(M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
|
||||
"SM100_MMA_F16BF16 N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
|
||||
or a multiple of 16 between 16 and 256 for M=128.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16 A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
@@ -217,16 +197,6 @@ struct SM100_MMA_F16BF16_TS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_a);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
if (cute::elect_one_sync()) {
|
||||
asm volatile(
|
||||
@@ -245,13 +215,101 @@ struct SM100_MMA_F16BF16_TS
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major, uint32_t ScaleC,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
|
||||
struct SM100_MMA_F16BF16_SS_SCALED
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16_SS_SCALED M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
|
||||
(M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
|
||||
"SM100_MMA_F16BF16_SS_SCALED N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
|
||||
or a multiple of 16 between 16 and 256 for M=128.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
using BRegisters = uint64_t[1];
|
||||
using CRegisters = uint32_t[1];
|
||||
|
||||
CUTE_HOST_DEVICE static void
|
||||
fma(uint64_t const& desc_a,
|
||||
uint64_t const& desc_b,
|
||||
uint32_t const& tmem_c,
|
||||
uint32_t const& accumulate,
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED)
|
||||
if (cute::elect_one_sync()) {
|
||||
// ScaleC input should be a literal or compile time constant
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
asm volatile(
|
||||
"{\n\t"
|
||||
".reg .pred p;\n\t"
|
||||
"setp.ne.b32 p, %4, 0;\n\t"
|
||||
"tcgen05.mma.cta_group::1.kind::f16 [%0], %1, %2, %3, {%5, %6, %7, %8}, p, %9; \n\t"
|
||||
"}\n"
|
||||
:
|
||||
: "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(accumulate),
|
||||
"r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]), "n"(ScaleC));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_SS without CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major, uint32_t ScaleC,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_F16BF16_TS_SCALED
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16_TS_SCALED M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
|
||||
(M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
|
||||
"SM100_MMA_F16BF16_TS_SCALED N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
|
||||
or a multiple of 16 between 16 and 256 for M=128.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16_TS_SCALED A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint32_t[1];
|
||||
using BRegisters = uint64_t[1];
|
||||
using CRegisters = uint32_t[1];
|
||||
|
||||
CUTE_HOST_DEVICE static void
|
||||
fma(uint32_t const& tmem_a,
|
||||
uint64_t const& desc_b,
|
||||
uint32_t const& tmem_c,
|
||||
uint32_t const& accumulate,
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED)
|
||||
if (cute::elect_one_sync()) {
|
||||
// ScaleC input should be a literal or compile time constant
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
asm volatile(
|
||||
"{\n\t"
|
||||
".reg .pred p;\n\t"
|
||||
"setp.ne.b32 p, %4, 0;\n\t"
|
||||
"tcgen05.mma.cta_group::1.kind::f16 [%0], [%1], %2, %3, {%5, %6, %7, %8}, p, %9; \n\t"
|
||||
"}\n"
|
||||
:
|
||||
: "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(accumulate),
|
||||
"r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]), "n"(ScaleC));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_TS_SCALED without CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
|
||||
struct SM100_MMA_TF32_2x1SM_SS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_TF32 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_TF32 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_TF32_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_TF32_2x1SM_SS N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -266,15 +324,6 @@ struct SM100_MMA_TF32_2x1SM_SS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("Umma TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -289,7 +338,7 @@ struct SM100_MMA_TF32_2x1SM_SS
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_TF32_2x1SM_SS without SM100_MMA_TF32_2x1SM_SS");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_TF32_2x1SM_SS without CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -299,8 +348,8 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
|
||||
struct SM100_MMA_F16BF16_2x1SM_SS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_F16BF16 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_SS N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -315,15 +364,6 @@ struct SM100_MMA_F16BF16_2x1SM_SS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("Umma TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -338,7 +378,7 @@ struct SM100_MMA_F16BF16_2x1SM_SS
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_SS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_SS without CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -349,9 +389,9 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_TF32_2x1SM_TS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_TF32 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_TF32 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_TF32 A from TMEM can't be transposed");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_TF32_2x1SM_TS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_TF32_2x1SM_TS N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_TF32_2x1SM_TS A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint32_t[1];
|
||||
@@ -366,14 +406,6 @@ struct SM100_MMA_TF32_2x1SM_TS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print(desc_i);
|
||||
print("Umma TMEM-A addr: 0x%08x\n", tmem_a);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("Umma TMEM-C addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -399,9 +431,9 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_F16BF16_2x1SM_TS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_F16BF16 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16 A from TMEM can't be transposed");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_TS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_TS N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16_2x1SM_TS A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint32_t[1];
|
||||
@@ -416,14 +448,6 @@ struct SM100_MMA_F16BF16_2x1SM_TS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print(desc_i);
|
||||
print("Umma TMEM-A addr: 0x%08x\n", tmem_a);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("Umma TMEM-C addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -438,7 +462,91 @@ struct SM100_MMA_F16BF16_2x1SM_TS
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_TS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_TS without CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major, uint32_t ScaleC,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
|
||||
struct SM100_MMA_F16BF16_2x1SM_SS_SCALED
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_SS_SCALED M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_SS_SCALED N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
using BRegisters = uint64_t[1];
|
||||
using CRegisters = uint32_t[1];
|
||||
|
||||
CUTE_HOST_DEVICE static void
|
||||
fma(uint64_t const& desc_a,
|
||||
uint64_t const& desc_b,
|
||||
uint32_t const& tmem_c,
|
||||
uint32_t const& accumulate,
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED)
|
||||
if (cute::elect_one_sync()) {
|
||||
// ScaleC input should be a literal or compile time constant
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
"{\n\t"
|
||||
".reg .pred p;\n\t"
|
||||
"setp.ne.b32 p, %4, 0;\n\t"
|
||||
"tcgen05.mma.cta_group::2.kind::f16 [%0], %1, %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p, %13; \n\t"
|
||||
"}\n"
|
||||
:
|
||||
: "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(accumulate),
|
||||
"r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]), "n"(ScaleC));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_SS_SCALED without CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major, uint32_t ScaleC,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_F16BF16_2x1SM_TS_SCALED
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_TS_SCALED M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_TS_SCALED N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16_2x1SM_TS_SCALED A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint32_t[1];
|
||||
using BRegisters = uint64_t[1];
|
||||
using CRegisters = uint32_t[1];
|
||||
|
||||
CUTE_HOST_DEVICE static void
|
||||
fma(uint32_t const& tmem_a,
|
||||
uint64_t const& desc_b,
|
||||
uint32_t const& tmem_c,
|
||||
uint32_t const& accumulate,
|
||||
uint64_t idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED)
|
||||
if (cute::elect_one_sync()) {
|
||||
// ScaleC input should be a literal or compile time constant
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
"{\n\t"
|
||||
".reg .pred p;\n\t"
|
||||
"setp.ne.b32 p, %4, 0;\n\t"
|
||||
"tcgen05.mma.cta_group::2.kind::f16 [%0], [%1], %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p, %13; \n\t"
|
||||
"}\n"
|
||||
:
|
||||
: "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(accumulate),
|
||||
"r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]), "n"(ScaleC));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_TS_SCALED without CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -448,9 +556,9 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_S8_SS
|
||||
{
|
||||
static_assert(is_same_v<c_type, int32_t>, "SM100_MMA_S8 result type can only be int32_t.");
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_S8 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_S8 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert(is_same_v<c_type, int32_t>, "SM100_MMA_S8_SS result type can only be int32_t.");
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_S8_SS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert(N == 8 || ((N % 16 == 0) && (16 <= N) && (N <= 256)), "SM100_MMA_S8_SS N-mode size should be 8 or a multiple of 16 between 16 and 256.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -465,16 +573,6 @@ struct SM100_MMA_S8_SS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -488,7 +586,7 @@ struct SM100_MMA_S8_SS
|
||||
"r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_SS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_SS without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -499,9 +597,9 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_S8_TS
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_S8 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_S8 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_S8 A from TMEM can't be transposed");
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_S8_TS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert(N == 8 || ((N % 16 == 0) && (16 <= N) && (N <= 256)), "SM100_MMA_S8_TS N-mode size should be 8 or a multiple of 16 between 16 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_S8_TS A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint32_t[1];
|
||||
@@ -516,16 +614,6 @@ struct SM100_MMA_S8_TS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_a);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -539,7 +627,7 @@ struct SM100_MMA_S8_TS
|
||||
"r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_TS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_TS without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -549,8 +637,8 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_S8_2x1SM_SS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_S8 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_S8 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_S8_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_S8_2x1SM_SS N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -565,16 +653,6 @@ struct SM100_MMA_S8_2x1SM_SS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("Umma TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -589,7 +667,7 @@ struct SM100_MMA_S8_2x1SM_SS
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_2x1SM_SS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_2x1SM_SS without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -600,9 +678,9 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_S8_2x1SM_TS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_S8 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_S8 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_S8 A from TMEM can't be transposed");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_S8_2x1SM_TS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_S8_2x1SM_TS N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_S8_2x1SM_TS A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint32_t[1];
|
||||
@@ -617,16 +695,6 @@ struct SM100_MMA_S8_2x1SM_TS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print("Umma TMEM addr: 0x%08x\n", tmem_a);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("Umma TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -641,13 +709,15 @@ struct SM100_MMA_S8_2x1SM_TS
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_2x1SM_TS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_2x1SM_TS without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
struct SM100_MMA_F8F6F4_SS
|
||||
{
|
||||
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
using BRegisters = uint64_t[1];
|
||||
@@ -661,16 +731,6 @@ struct SM100_MMA_F8F6F4_SS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -684,7 +744,7 @@ struct SM100_MMA_F8F6F4_SS
|
||||
"r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_SS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_SS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -694,8 +754,8 @@ template <class a_type, class b_type, class c_type, class sf_type,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
|
||||
struct SM100_MMA_MXF8F6F4_SS
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_MXF8F6F4 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_MXF8F6F4 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert(M == 128, "SM100_MMA_MXF8F6F4_SS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_MXF8F6F4_SS N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -714,19 +774,6 @@ struct SM100_MMA_MXF8F6F4_SS
|
||||
uint32_t const& tsfb_addr)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptorBlockScaled desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
print("Umma SFA TMEM addr: 0x%08x\n", tsfa_addr);
|
||||
print("Umma SFB TMEM addr: 0x%08x\n", tsfb_addr);
|
||||
print("===================================\n");
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
asm volatile(
|
||||
"{\n\t"
|
||||
@@ -738,7 +785,7 @@ struct SM100_MMA_MXF8F6F4_SS
|
||||
: "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC), "r"(tsfa_addr), "r"(tsfb_addr));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_SS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_SS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -749,9 +796,12 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_F8F6F4_TS
|
||||
{
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_F8F6F4 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_F8F6F4 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F8F6F4 A from TMEM can't be transposed");
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_F8F6F4_TS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
|
||||
(M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
|
||||
"SM100_MMA_F8F6F4_TS N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
|
||||
or a multiple of 16 between 16 and 256 for M=128.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F8F6F4_TS A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint32_t[1];
|
||||
@@ -766,16 +816,6 @@ struct SM100_MMA_F8F6F4_TS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_a);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[4] = {0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -789,7 +829,7 @@ struct SM100_MMA_F8F6F4_TS
|
||||
"r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_TS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_TS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -800,9 +840,9 @@ template <class a_type, class b_type, class c_type,
|
||||
UMMA::Saturate c_sat = UMMA::Saturate::False>
|
||||
struct SM100_MMA_F8F6F4_2x1SM_TS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F8F6F4 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_F8F6F4 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F8F6F4 A from TMEM can't be transposed");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F8F6F4_2x1SM_TS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F8F6F4_2x1SM_TS N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_F8F6F4_2x1SM_TS A from TMEM can't be transposed");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint32_t[1];
|
||||
@@ -817,15 +857,6 @@ struct SM100_MMA_F8F6F4_2x1SM_TS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_a);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("UMMA TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -840,13 +871,13 @@ struct SM100_MMA_F8F6F4_2x1SM_TS
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_TS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_TS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
struct SM100_MMA_F8F6F4_2x1SM_SS
|
||||
{
|
||||
{
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
using BRegisters = uint64_t[1];
|
||||
@@ -860,16 +891,6 @@ struct SM100_MMA_F8F6F4_2x1SM_SS
|
||||
uint64_t const& idescE)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptor desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("Umma TMEM addr: 0x%08x\n", tmem_c);
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
asm volatile(
|
||||
@@ -884,7 +905,7 @@ struct SM100_MMA_F8F6F4_2x1SM_SS
|
||||
"r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_2x1SM_SS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_2x1SM_SS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -894,8 +915,8 @@ template <class a_type, class b_type, class c_type, class sf_type,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
|
||||
struct SM100_MMA_MXF8F6F4_2x1SM_SS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_MXF8F6F4 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF8F6F4 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert(M == 256, "SM100_MMA_MXF8F6F4_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF8F6F4_2x1SM_SS N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -912,19 +933,6 @@ struct SM100_MMA_MXF8F6F4_2x1SM_SS
|
||||
uint32_t const& tsfb_addr)
|
||||
{
|
||||
#if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
UMMA::InstrDescriptorBlockScaled desc_i;
|
||||
desc_i.desc_ = uint32_t(idescE >> 32);
|
||||
print(desc_i);
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_a));
|
||||
print(reinterpret_cast<GmmaDescriptor const&>(desc_b));
|
||||
print("Umma TMEM addr: 0x%08x\n", tmem_c);
|
||||
print("Umma SFA TMEM addr: 0x%08x\n", tsfa_addr);
|
||||
print("Umma SFB TMEM addr: 0x%08x\n", tsfb_addr);
|
||||
print("===================================\n");
|
||||
}
|
||||
#endif
|
||||
if (cute::elect_one_sync()) {
|
||||
asm volatile(
|
||||
"{\n\t"
|
||||
@@ -937,7 +945,7 @@ struct SM100_MMA_MXF8F6F4_2x1SM_SS
|
||||
"r"(tsfa_addr), "r"(tsfb_addr));
|
||||
}
|
||||
#else
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF8F6F4_2x1SM_SS without CUTE_ARCH_MMA_SM100A_ENABLED");
|
||||
CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF8F6F4_2x1SM_SS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -948,9 +956,9 @@ template <class a_type, class b_type, class c_type, class sf_type,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
|
||||
struct SM100_MMA_MXF4_SS
|
||||
{
|
||||
static_assert(M == 128, "SM100_MMA_MXF4 M-mode size should be 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF4 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert((VS == 16) || (VS == 32), "Vector size can only be 16 or 32.");
|
||||
static_assert(M == 128, "SM100_MMA_MXF4_SS M-mode size should be 128 for 1 CTA cluster OMMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_MXF4_SS N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
static_assert((VS == 16) || (VS == 32), "SM100_MMA_MXF4_SS Vector size can only be 16 or 32.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
@@ -1013,9 +1021,9 @@ template <class a_type, class b_type, class c_type, class sf_type,
|
||||
UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
|
||||
struct SM100_MMA_MXF4_2x1SM_SS
|
||||
{
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_MXF4 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF4 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert((VS == 16) || (VS == 32), "Vector size can only be 16 or 32.");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_MXF4_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF4_2x1SM_SS N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
static_assert((VS == 16) || (VS == 32), "SM100_MMA_MXF4_2x1SM_SS Vector size can only be 16 or 32.");
|
||||
|
||||
using DRegisters = void;
|
||||
using ARegisters = uint64_t[1];
|
||||
|
||||
@@ -521,15 +521,6 @@ make_cotiled_copy(Copy_Atom<Args...> const& copy_atom,
|
||||
// Check validity
|
||||
CUTE_STATIC_ASSERT_V(coalesce(composition(data_layout, layout<1>(layout_tv_data))) == coalesce(layout<1>(atom_tv_layout)),
|
||||
"The memory pointed to by AtomTVLayout does not exist in the DataLayout.");
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print("data_layout : "); print(data_layout); print("\n");
|
||||
print("atom_tv_layout : "); print(atom_tv_layout); print("\n");
|
||||
print("layout_tv_data : "); print(layout_tv_data); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Tiler -- Find the active elements in the DATA tensor and generate a tiler to extract them
|
||||
//
|
||||
@@ -552,15 +543,6 @@ make_cotiled_copy(Copy_Atom<Args...> const& copy_atom,
|
||||
|
||||
// (tid,vid) -> tile_coord
|
||||
auto layout_tv = composition(left_inverse(tile2data), layout_tv_data);
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print("tiler : "); print(tiler); print("\n");
|
||||
print("tile2data : "); print(tile2data); print("\n");
|
||||
print("layout_tv : "); print(layout_tv); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return make_tiled_copy_impl(copy_atom, layout_tv, tiler);
|
||||
}
|
||||
|
||||
|
||||
@@ -394,15 +394,6 @@ make_tmem_warp_partitioner(Tensor<TEngine,TLayout> const& tmem)
|
||||
|
||||
// wid -> tmem_coord
|
||||
auto layout_t_tmem = composition(inv_tmem_layout, atom_t_layout);
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print("input : "); print(tmem.data()); print(" o "); print(tmem_layout); print("\n");
|
||||
print("atom_t_layout : "); print(atom_t_layout); print("\n");
|
||||
print("layout_tv_tmem : "); print(layout_tv_tmem); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Tiler -- Find the active elements in the TMEM tensor and generate a tiler to extract them
|
||||
//
|
||||
@@ -425,15 +416,6 @@ make_tmem_warp_partitioner(Tensor<TEngine,TLayout> const& tmem)
|
||||
|
||||
// wid -> tile_coord
|
||||
auto layout_tv = composition(left_inverse(tile2tmem), layout_t_tmem);
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print("tiler : "); print(tiler); print("\n");
|
||||
print("tile2tmem : "); print(tile2tmem); print("\n");
|
||||
print("layout_tv : "); print(layout_tv); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return make_tiler_impl(layout_tv, tiler);
|
||||
}
|
||||
|
||||
|
||||
@@ -1374,19 +1374,6 @@ tma_partition(Copy_Atom<Args...> const& copy_atom,
|
||||
// Transform tile mode and coalesce
|
||||
Tensor gtensor_v = coalesce(gtensor.compose(glayout_V), Shape<Shape<_1,_1>>{}); // ((TMA,TMA_Iter), Rest...)
|
||||
Tensor stensor_v = coalesce(stensor.compose(slayout_V), Shape<Shape<_1,_1>>{}); // ((TMA,TMA_Iter), Rest...)
|
||||
|
||||
#if 0
|
||||
if (thread0()) {
|
||||
print("cta_coord : "); print(cta_coord); print("\n");
|
||||
print("cta_layout : "); print(cta_layout); print("\n");
|
||||
print("gtensor : "); print(gtensor); print("\n");
|
||||
print("stensor : "); print(stensor); print("\n");
|
||||
print("layout_V : "); print(layout_V); print("\n");
|
||||
print("gtensor_v : "); print(gtensor_v); print("\n");
|
||||
print("stensor_v : "); print(stensor_v); print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Offset inside the TMA-mode for the multicast
|
||||
auto multicast_offset = cta_layout(cta_coord) * (size(tma_layout_v) / cosize(cta_layout));
|
||||
auto multicast_coord = make_coord(make_coord(multicast_offset, Int<0>{}));
|
||||
|
||||
@@ -157,7 +157,6 @@ struct MMA_Atom<MMA_Traits<MMAOperation, Args...>>
|
||||
|
||||
|| (sizeof_bits_v<typename remove_cvref_t<ATensor>::value_type> == 8 &&
|
||||
(sizeof_bits_v<ValTypeA> == 8 || sizeof_bits_v<ValTypeA> == 6 || sizeof_bits_v<ValTypeA> == 4))
|
||||
|
||||
, "Expecting ValTypeA type");
|
||||
return make_tensor<FrgTypeA>(static_cast<ATensor&&>(atensor));
|
||||
} else {
|
||||
|
||||
@@ -59,7 +59,6 @@ namespace UMMA {
|
||||
// Common layouts for UMMA Shared Memory //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
// TODO: Extend for remaining sm100 new layouts
|
||||
using cute::GMMA::Layout_MN_INTER_Atom;
|
||||
using cute::GMMA::Layout_MN_SW32_Atom;
|
||||
using cute::GMMA::Layout_MN_SW64_Atom;
|
||||
@@ -275,19 +274,6 @@ make_umma_desc(Tensor<TEngine,TLayout> const& tensor)
|
||||
} else {
|
||||
static_assert(MajorMode != UMMA::Major::MN && MajorMode != UMMA::Major::K, "Unrecognized MajorMode!");
|
||||
}
|
||||
|
||||
#if 0
|
||||
// DEBUG and SANITY
|
||||
assert((start_address & 0b0000001111) == 0); // Must be 16B aligned (4LSB are 0) no negotiation
|
||||
assert((start_address & 0b1110000000) == 0); // Assert base_offset is 0, generalize later
|
||||
if (thread0()) {
|
||||
print("smem_desc input tensor: "); print(tensor.data()); print(" o "); print(tensor.layout()); print("\n");
|
||||
print("smem_desc uint128_t tensor: "); print(u128_tensor.data()); print(" o "); print(u128_tensor.layout()); print("\n");
|
||||
//print(" desc canonical layout: "); print(canonical_layout); print("\n");
|
||||
print(desc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
@@ -514,7 +500,7 @@ struct tmem_frg : tmem_frg_base
|
||||
"UMMA_2SM only accepts Interleaved or Duplicated");
|
||||
static_assert(M_MMA == 32 || M_MMA == 64 || M_MMA == 128, "UMMA_2SM M-mode size should be 32 or 64 or 128.");
|
||||
|
||||
if constexpr (M_MMA == 32) // TODO: Implement Duplicated mode for M_MMA = 32
|
||||
if constexpr (M_MMA == 32)
|
||||
{
|
||||
static_assert(TmemAlloc == UMMA::TmemAllocMode::Interleaved, "Only TmemAllocMode::Interleaved is supported for UMMA_2SM M_MMA=32");
|
||||
// The "1x4" layout atom: (M,N) -> tmem_addr
|
||||
@@ -1013,7 +999,7 @@ struct MMA_Traits<SM100_MMA_TF32_SS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 32, "SM100_MMA_TF32 supports 32bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 32, "SM100_MMA_TF32_SS supports 32bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1077,7 +1063,7 @@ struct MMA_Traits<SM100_MMA_F16BF16_SS<a_type, b_type, c_type,
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16 supports 16bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16_SS supports 16bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1142,7 +1128,7 @@ struct MMA_Traits<SM100_MMA_TF32_TS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 32, "SM100_MMA_TF32 supports 32bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 32, "SM100_MMA_TF32_TS supports 32bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_1sm<a_type, a_type, UMMA::TmemAllocMode::NonInterleaved>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1208,7 +1194,7 @@ struct MMA_Traits<SM100_MMA_F16BF16_TS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16 supports 16bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16_TS supports 16bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_1sm<a_type, a_type, UMMA::TmemAllocMode::NonInterleaved>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1261,6 +1247,155 @@ struct MMA_Traits<SM100_MMA_F16BF16_TS<a_type, b_type, c_type,
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major,
|
||||
uint32_t ScaleC, UMMA::ScaleIn a_neg, UMMA::ScaleIn b_neg>
|
||||
struct MMA_Traits<SM100_MMA_F16BF16_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg>>
|
||||
{
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16_SS_SCALED supports 16bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
using FrgTypeC = UMMA::tmem_frg_1sm<c_type>;
|
||||
|
||||
// Logical shape-K is always 256bits, transform to units of elements
|
||||
static constexpr int K = 256 / cute::sizeof_bits<ValTypeA>::value;
|
||||
|
||||
static constexpr uint32_t ScalingFactor = ScaleC;
|
||||
|
||||
using Shape_MNK = Shape<Int<M>,Int<N>,Int<K>>;
|
||||
using ThrID = Layout<_1>;
|
||||
using ALayout = Layout<Shape <_1,Shape <Int<M>,Int<K>>>,
|
||||
Stride<_0,Stride< _1,Int<M>>>>;
|
||||
using BLayout = Layout<Shape <_1,Shape <Int<N>,Int<K>>>,
|
||||
Stride<_0,Stride< _1,Int<N>>>>;
|
||||
using CLayout = Layout<Shape <_1,Shape <Int<M>,Int<N>>>,
|
||||
Stride<_0,Stride< _1,Int<M>>>>;
|
||||
|
||||
// Accumulate or overwrite C. 1: read C, 0: ignore C [clear accumulators]
|
||||
UMMA::ScaleOut accumulate_ = UMMA::ScaleOut::One;
|
||||
|
||||
UMMA::InstrDescriptor idesc_ = UMMA::make_instr_desc<
|
||||
a_type, b_type, c_type, M, N, a_major, b_major, a_neg, b_neg>();
|
||||
|
||||
template <class TD, class DLayout,
|
||||
class TA, class ALayout,
|
||||
class TB, class BLayout,
|
||||
class TC, class CLayout>
|
||||
CUTE_HOST_DEVICE constexpr friend
|
||||
void
|
||||
mma_unpack(MMA_Traits const& traits,
|
||||
Tensor<TD, DLayout> & D,
|
||||
Tensor<TA, ALayout> const& A,
|
||||
Tensor<TB, BLayout> const& B,
|
||||
Tensor<TC, CLayout> const& C)
|
||||
{
|
||||
static_assert(is_tmem<TD>::value, "Expected tmem in MMA_Atom::call");
|
||||
static_assert(is_rmem<TA>::value, "Expected desc registers in MMA_Atom::call");
|
||||
static_assert(is_rmem<TB>::value, "Expected desc registers in MMA_Atom::call");
|
||||
static_assert(is_tmem<TC>::value, "Expected tmem in MMA_Atom::call");
|
||||
|
||||
uint64_t desc_a = A[0];
|
||||
uint64_t desc_b = B[0];
|
||||
uint32_t tmem_c = raw_pointer_cast(D.data());
|
||||
uint64_t idesc = UMMA::make_runtime_instr_desc<>(traits.idesc_);
|
||||
|
||||
SM100_MMA_F16BF16_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg>::fma(desc_a, desc_b, tmem_c, uint32_t(traits.accumulate_), idesc);
|
||||
|
||||
}
|
||||
|
||||
template <uint32_t NewScaleC>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
NewScaleC, a_neg, b_neg>>
|
||||
with(UMMA::ScaleOut accumulate, cute::integral_constant<uint32_t, NewScaleC> scaleC) const {
|
||||
return {accumulate, idesc_};
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major,
|
||||
uint32_t ScaleC, UMMA::ScaleIn a_neg, UMMA::ScaleIn b_neg, UMMA::Saturate c_sat>
|
||||
struct MMA_Traits<SM100_MMA_F16BF16_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg, c_sat>>
|
||||
{
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16_TS_SCALED supports 16bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_1sm<a_type, a_type, UMMA::TmemAllocMode::NonInterleaved>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
using FrgTypeC = UMMA::tmem_frg_1sm<c_type, int32_t, UMMA::TmemAllocMode::NonInterleaved>;
|
||||
|
||||
// Logical shape-K is always 256 bits; transform to units of elements
|
||||
static constexpr int K = 256 / cute::sizeof_bits<ValTypeA>::value;
|
||||
|
||||
static constexpr uint32_t ScalingFactor = ScaleC;
|
||||
|
||||
using Shape_MNK = Shape<Int<M>,Int<N>,Int<K>>;
|
||||
using ThrID = Layout<_1>;
|
||||
using ALayout = Layout<Shape <_1,Shape <Int<M>,Int<K>>>,
|
||||
Stride<_0,Stride< _1,Int<M>>>>;
|
||||
using BLayout = Layout<Shape <_1,Shape <Int<N>,Int<K>>>,
|
||||
Stride<_0,Stride< _1,Int<N>>>>;
|
||||
using CLayout = Layout<Shape <_1,Shape <Int<M>,Int<N>>>,
|
||||
Stride<_0,Stride< _1,Int<M>>>>;
|
||||
|
||||
// Accumulate or overwrite C. 1: read C, 0: ignore C [clear accumulators]
|
||||
UMMA::ScaleOut accumulate_ = UMMA::ScaleOut::One;
|
||||
|
||||
UMMA::InstrDescriptor idesc_ = UMMA::make_instr_desc<
|
||||
a_type, b_type, c_type, M, N, a_major, b_major, a_neg, b_neg, c_sat>();
|
||||
|
||||
template <class TD, class DLayout,
|
||||
class TA, class ALayout,
|
||||
class TB, class BLayout,
|
||||
class TC, class CLayout>
|
||||
CUTE_HOST_DEVICE constexpr friend
|
||||
void
|
||||
mma_unpack(MMA_Traits const& traits,
|
||||
Tensor<TD, DLayout> & D,
|
||||
Tensor<TA, ALayout> const& A,
|
||||
Tensor<TB, BLayout> const& B,
|
||||
Tensor<TC, CLayout> const& C)
|
||||
{
|
||||
static_assert(is_tmem<TD>::value, "Expected tmem in MMA_Atom::call");
|
||||
static_assert(is_tmem<TA>::value, "Expected tmem in MMA_Atom::call");
|
||||
static_assert(is_rmem<TB>::value, "Expected desc registers in MMA_Atom::call");
|
||||
static_assert(is_tmem<TC>::value, "Expected tmem in MMA_Atom::call");
|
||||
|
||||
uint32_t tmem_a = raw_pointer_cast(A.data());
|
||||
uint64_t desc_b = B[0];
|
||||
uint32_t tmem_c = raw_pointer_cast(D.data());
|
||||
uint64_t idesc = UMMA::make_runtime_instr_desc<>(traits.idesc_);
|
||||
|
||||
SM100_MMA_F16BF16_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg>::fma(tmem_a, desc_b, tmem_c, uint32_t(traits.accumulate_), idesc);
|
||||
}
|
||||
|
||||
template <uint32_t NewScaleC>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
NewScaleC, a_neg, b_neg, c_sat>>
|
||||
with(UMMA::ScaleOut accumulate, cute::integral_constant<uint32_t, NewScaleC> scaleC) const {
|
||||
return {accumulate, idesc_};
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N,
|
||||
UMMA::Major a_major, UMMA::Major b_major,
|
||||
@@ -1273,7 +1408,7 @@ struct MMA_Traits<SM100_MMA_TF32_2x1SM_SS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 32, "SM100_MMA_TF32 supports 32bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 32, "SM100_MMA_TF32_2x1SM_SS supports 32bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1338,7 +1473,7 @@ struct MMA_Traits<SM100_MMA_F16BF16_2x1SM_SS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16 supports 16bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16_2x1SM_SS supports 16bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1404,7 +1539,7 @@ struct MMA_Traits<SM100_MMA_TF32_2x1SM_TS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 32, "SM100_MMA_TF32 supports 32bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 32, "SM100_MMA_TF32_2x1SM_TS supports 32bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_2sm<a_type, a_type, UMMA::TmemAllocMode::Duplicated>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1470,7 +1605,7 @@ struct MMA_Traits<SM100_MMA_F16BF16_2x1SM_TS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16 supports 16bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16_2x1SM_TS supports 16bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_2sm<a_type, a_type, UMMA::TmemAllocMode::Duplicated>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1523,6 +1658,152 @@ struct MMA_Traits<SM100_MMA_F16BF16_2x1SM_TS<a_type, b_type, c_type,
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major,
|
||||
uint32_t ScaleC, UMMA::ScaleIn a_neg, UMMA::ScaleIn b_neg>
|
||||
struct MMA_Traits<SM100_MMA_F16BF16_2x1SM_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg>>
|
||||
{
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16_2x1SM_SS_SCALED supports 16bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
using FrgTypeC = UMMA::tmem_frg_2sm<c_type>;
|
||||
|
||||
// Size of instructions's K extent is always 256bits, convert to units of element
|
||||
constexpr static int K = 256 / cute::sizeof_bits<ValTypeA>::value;
|
||||
constexpr static uint32_t ScalingFactor = ScaleC;
|
||||
|
||||
using Shape_MNK = Shape<Int<M>,Int<N>,Int<K>>;
|
||||
using ThrID = Layout<_2>;
|
||||
using ALayout = Layout<Shape < _2,Shape <Int<M/2>,Int<K>>>,
|
||||
Stride<Int<M/2>,Stride< _1,Int<M>>>>;
|
||||
using BLayout = Layout<Shape < _2,Shape <Int<N/2>,Int<K>>>,
|
||||
Stride<Int<N/2>,Stride< _1,Int<N>>>>;
|
||||
using CLayout = Layout<Shape < _2,Shape <Int<M/2>,Int<N>>>,
|
||||
Stride<Int<M/2>,Stride< _1,Int<M>>>>;
|
||||
|
||||
// Accumulate or overwrite C. 1: read C, 0: ignore C [clear accumulators]
|
||||
UMMA::ScaleOut accumulate_ = UMMA::ScaleOut::One;
|
||||
|
||||
UMMA::InstrDescriptor idesc_ = UMMA::make_instr_desc<
|
||||
a_type, b_type, c_type, M, N, a_major, b_major, a_neg, b_neg>();
|
||||
|
||||
template <class TD, class DLayout,
|
||||
class TA, class ALayout,
|
||||
class TB, class BLayout,
|
||||
class TC, class CLayout>
|
||||
CUTE_HOST_DEVICE constexpr friend
|
||||
void
|
||||
mma_unpack(MMA_Traits const& traits,
|
||||
Tensor<TD, DLayout> & D,
|
||||
Tensor<TA, ALayout> const& A,
|
||||
Tensor<TB, BLayout> const& B,
|
||||
Tensor<TC, CLayout> const& C)
|
||||
{
|
||||
static_assert(is_tmem<TD>::value, "Expected tmem in MMA_Atom::call");
|
||||
static_assert(is_rmem<TA>::value, "Expected desc registers in MMA_Atom::call");
|
||||
static_assert(is_rmem<TB>::value, "Expected desc registers in MMA_Atom::call");
|
||||
static_assert(is_tmem<TC>::value, "Expected tmem in MMA_Atom::call");
|
||||
|
||||
uint64_t desc_a = A[0];
|
||||
uint64_t desc_b = B[0];
|
||||
uint32_t tmem_c = raw_pointer_cast(D.data());
|
||||
uint64_t idesc = UMMA::make_runtime_instr_desc<>(traits.idesc_);
|
||||
|
||||
SM100_MMA_F16BF16_2x1SM_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg>::fma(desc_a, desc_b, tmem_c, uint32_t(traits.accumulate_), idesc);
|
||||
}
|
||||
|
||||
template <uint32_t NewScaleC>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_2x1SM_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
NewScaleC, a_neg, b_neg>>
|
||||
with(UMMA::ScaleOut accumulate, cute::integral_constant<uint32_t, NewScaleC> scaleC) const {
|
||||
return {accumulate, idesc_};
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major,
|
||||
uint32_t ScaleC, UMMA::ScaleIn a_neg, UMMA::ScaleIn b_neg, UMMA::Saturate c_sat>
|
||||
struct MMA_Traits<SM100_MMA_F16BF16_2x1SM_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg, c_sat>>
|
||||
{
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 16, "SM100_MMA_F16BF16_2x1SM_TS_SCALED supports 16bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_2sm<a_type, a_type, UMMA::TmemAllocMode::Duplicated>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
using FrgTypeC = UMMA::tmem_frg_2sm<c_type>;
|
||||
|
||||
// Size of instructions' K extent is always 256 bits; convert to units of element
|
||||
constexpr static int K = 256 / cute::sizeof_bits<ValTypeA>::value;
|
||||
constexpr static uint32_t ScalingFactor = ScaleC;
|
||||
|
||||
using Shape_MNK = Shape<Int<M>,Int<N>,Int<K>>;
|
||||
using ThrID = Layout<_2>;
|
||||
using ALayout = Layout<Shape < _2,Shape <Int<M/2>,Int<K>>>,
|
||||
Stride<Int<M/2>,Stride< _1,Int<M>>>>;
|
||||
using BLayout = Layout<Shape < _2,Shape <Int<N/2>,Int<K>>>,
|
||||
Stride<Int<N/2>,Stride< _1,Int<N>>>>;
|
||||
using CLayout = Layout<Shape < _2,Shape <Int<M/2>,Int<N>>>,
|
||||
Stride<Int<M/2>,Stride< _1,Int<M>>>>;
|
||||
|
||||
// Accumulate or overwrite C. 1: read C, 0: ignore C [clear accumulators]
|
||||
UMMA::ScaleOut accumulate_ = UMMA::ScaleOut::One;
|
||||
|
||||
UMMA::InstrDescriptor idesc_ = UMMA::make_instr_desc<
|
||||
a_type, b_type, c_type, M, N, a_major, b_major, a_neg, b_neg, c_sat>();
|
||||
|
||||
template <class TD, class DLayout,
|
||||
class TA, class ALayout,
|
||||
class TB, class BLayout,
|
||||
class TC, class CLayout>
|
||||
CUTE_HOST_DEVICE constexpr friend
|
||||
void
|
||||
mma_unpack(MMA_Traits const& traits,
|
||||
Tensor<TD, DLayout> & D,
|
||||
Tensor<TA, ALayout> const& A,
|
||||
Tensor<TB, BLayout> const& B,
|
||||
Tensor<TC, CLayout> const& C)
|
||||
{
|
||||
static_assert(is_tmem<TD>::value, "Expected tmem in MMA_Atom::call");
|
||||
static_assert(is_tmem<TA>::value, "Expected desc registers in MMA_Atom::call");
|
||||
static_assert(is_rmem<TB>::value, "Expected desc registers in MMA_Atom::call");
|
||||
static_assert(is_tmem<TC>::value, "Expected tmem in MMA_Atom::call");
|
||||
|
||||
uint64_t tmem_a = raw_pointer_cast(A.data());
|
||||
uint64_t desc_b = B[0];
|
||||
uint32_t tmem_c = raw_pointer_cast(D.data());
|
||||
uint64_t idesc = UMMA::make_runtime_instr_desc<>(traits.idesc_);
|
||||
|
||||
SM100_MMA_F16BF16_2x1SM_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg, c_sat>::fma(tmem_a, desc_b, tmem_c, uint32_t(traits.accumulate_), idesc);
|
||||
}
|
||||
|
||||
template <uint32_t NewScaleC>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_2x1SM_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
NewScaleC, a_neg, b_neg, c_sat>>
|
||||
with(UMMA::ScaleOut accumulate, cute::integral_constant<uint32_t, NewScaleC> scaleC) const {
|
||||
return {accumulate, idesc_};
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N, UMMA::Major a_major, UMMA::Major b_major,
|
||||
UMMA::Saturate c_sat>
|
||||
@@ -1534,7 +1815,7 @@ struct MMA_Traits<SM100_MMA_S8_SS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 8, "SM100_MMA_S8 supports 8bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 8, "SM100_MMA_S8_SS supports 8bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1599,7 +1880,7 @@ struct MMA_Traits<SM100_MMA_S8_TS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 8, "SM100_MMA_S8 supports 8bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 8, "SM100_MMA_S8_TS supports 8bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_1sm<a_type, a_type, UMMA::TmemAllocMode::NonInterleaved>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1663,7 +1944,7 @@ struct MMA_Traits<SM100_MMA_S8_2x1SM_SS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 8, "SM100_MMA_S8 supports 8bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 8, "SM100_MMA_S8_2x1SM_SS supports 8bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1728,7 +2009,7 @@ struct MMA_Traits<SM100_MMA_S8_2x1SM_TS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 8, "SM100_MMA_S8 supports 8bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == cute::sizeof_bits_v<b_type> && cute::sizeof_bits_v<b_type> == 8, "SM100_MMA_S8_2x1SM_TS supports 8bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_2sm<a_type, a_type, UMMA::TmemAllocMode::Duplicated>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -1795,16 +2076,18 @@ struct MMA_Traits<SM100_MMA_F8F6F4_SS, a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4 supports types with leq 8bit types");
|
||||
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4_SS supports types with leq 8bit types");
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_F8F6F4_SS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
|
||||
(M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
|
||||
"SM100_MMA_F8F6F4_SS N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
|
||||
or a multiple of 16 between 16 and 256 for M=128.");
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
using FrgTypeC = UMMA::tmem_frg_1sm<c_type>;
|
||||
|
||||
static_assert(sizeof_bits_v<ValTypeA> <= sizeof_bits_v<uint8_t> &&
|
||||
sizeof_bits_v<ValTypeB> <= sizeof_bits_v<uint8_t>);
|
||||
static_assert(M == 64 || M == 128, "SM100_MMA_F8F6F4 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_F8F6F4 N-mode size should be a multiple of 8 between 8 and 256.");
|
||||
|
||||
// Logical shape-K is always 256bits, transform to units of elements
|
||||
constexpr static int K = 32;
|
||||
@@ -1863,7 +2146,7 @@ struct MMA_Traits<SM100_MMA_MXF8F6F4_SS<a_type, b_type, c_type, sf_type,
|
||||
using ValTypeC = c_type;
|
||||
using ValTypeSFA = sf_type;
|
||||
using ValTypeSFB = sf_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_MXF8F6F4 supports types with leq 8bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_MXF8F6F4_SS supports types with leq 8bit types");
|
||||
|
||||
// Logical shape-K is always 256bits, transform to units of elements
|
||||
constexpr static int K = 32;
|
||||
@@ -1953,7 +2236,7 @@ struct MMA_Traits<SM100_MMA_F8F6F4_TS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4 supports types with leq 8bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4_TS supports types with leq 8bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_1sm<a_type, a_type, UMMA::TmemAllocMode::NonInterleaved>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -2023,8 +2306,10 @@ struct MMA_Traits<SM100_MMA_F8F6F4_2x1SM_SS, a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4 supports types with leq 8bit types");
|
||||
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4_2x1SM_SS supports types with leq 8bit types");
|
||||
static_assert(M == 128 || M == 256, "SM100_MMA_F8F6F4_2x1SM_SS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
|
||||
static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F8F6F4_2x1SM_SS N-mode size should be a multiple of 32 between 32 and 256.");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
using FrgTypeC = UMMA::tmem_frg_2sm<c_type>;
|
||||
@@ -2034,9 +2319,6 @@ struct MMA_Traits<SM100_MMA_F8F6F4_2x1SM_SS, a_type, b_type, c_type,
|
||||
// Size of instructions's K extent is always 256bits, convert to units of element
|
||||
constexpr static int K = 32;
|
||||
|
||||
static_assert(M == 128 || M == 256, "MMA_F8F6F4 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
|
||||
static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "MMA_F8F6F4 N-mode size should be a multiple of 16 between 16 and 256.");
|
||||
|
||||
using Shape_MNK = Shape<Int<M>,Int<N>,Int<K>>;
|
||||
using ThrID = Layout<_2>;
|
||||
using ALayout = Layout<Shape < _2,Shape <Int<M/2>,Int<K>>>,
|
||||
@@ -2090,7 +2372,7 @@ struct MMA_Traits<SM100_MMA_F8F6F4_2x1SM_TS<a_type, b_type, c_type,
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4 supports types with leq 8bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4_2x1SM_TS supports types with leq 8bit types");
|
||||
|
||||
using FrgTypeA = UMMA::tmem_frg_2sm<a_type, a_type, UMMA::TmemAllocMode::Duplicated>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -2159,7 +2441,7 @@ struct MMA_Traits<SM100_MMA_MXF8F6F4_2x1SM_SS<a_type, b_type, c_type, sf_type,
|
||||
using ValTypeC = c_type;
|
||||
using ValTypeSFA = sf_type;
|
||||
using ValTypeSFB = sf_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_F8F6F4 supports types with leq 8bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> <= 8 && cute::sizeof_bits_v<b_type> <= 8, "SM100_MMA_MXF8F6F4_2x1SM_SS supports types with leq 8bit types");
|
||||
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
using FrgTypeB = UMMA::smem_desc<b_major>;
|
||||
@@ -2252,7 +2534,7 @@ struct MMA_Traits<SM100_MMA_MXF4_SS<a_type, b_type, c_type, sf_type,
|
||||
using ValTypeC = c_type;
|
||||
using ValTypeSFA = sf_type;
|
||||
using ValTypeSFB = sf_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == 4 && cute::sizeof_bits_v<b_type> == 4, "SM100_MMA_MXF4 supports 4bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == 4 && cute::sizeof_bits_v<b_type> == 4, "SM100_MMA_MXF4_SS supports 4bit types");
|
||||
|
||||
// Logical shape-K is always 256bits, transform to units of elements
|
||||
constexpr static int K = 64;
|
||||
@@ -2345,7 +2627,7 @@ struct MMA_Traits<SM100_MMA_MXF4_2x1SM_SS<a_type, b_type, c_type, sf_type,
|
||||
using ValTypeC = c_type;
|
||||
using ValTypeSFA = sf_type;
|
||||
using ValTypeSFB = sf_type;
|
||||
static_assert(cute::sizeof_bits_v<a_type> == 4 && cute::sizeof_bits_v<b_type> == 4, "SM100_MMA_MXF4 supports 4bit types");
|
||||
static_assert(cute::sizeof_bits_v<a_type> == 4 && cute::sizeof_bits_v<b_type> == 4, "SM100_MMA_MXF4_2x1SM_SS supports 4bit types");
|
||||
|
||||
// Logical shape-K is always 256bits, transform to units of elements
|
||||
constexpr static int K = 64;
|
||||
|
||||
@@ -295,19 +295,6 @@ make_gmma_desc(Tensor<TEngine,TLayout> const& tensor)
|
||||
} else {
|
||||
static_assert(MajorMode != Major::MN && MajorMode != Major::K, "Unrecognized MajorMode!");
|
||||
}
|
||||
|
||||
#if 0
|
||||
// DEBUG and SANITY
|
||||
assert((start_address & 0b0000001111) == 0); // Must be 16B aligned (4LSB are 0) no negotiation
|
||||
assert((start_address & 0b1110000000) == 0); // Assert base_offset is 0, generalize later
|
||||
if (thread0()) {
|
||||
print("smem_desc input tensor: "); print(tensor.data()); print(" o "); print(tensor.layout()); print("\n");
|
||||
print("smem_desc uint128_t tensor: "); print(u128_tensor.data()); print(" o "); print(u128_tensor.layout()); print("\n");
|
||||
//print(" desc canonical layout: "); print(canonical_layout); print("\n");
|
||||
print(desc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
||||
@@ -1685,7 +1685,7 @@ blocked_product(Layout<TShape,TStride> const& block,
|
||||
|
||||
auto result = logical_product(append<R>(block), append<R>(tiler));
|
||||
|
||||
return coalesce(zip(get<0>(result), get<1>(result)), tuple_repeat<R>(Int<1>{}));
|
||||
return zip(get<0>(result), get<1>(result));
|
||||
}
|
||||
|
||||
// raked_product -- Reproduce a block over a tiler with block-interleaving.
|
||||
@@ -1703,7 +1703,7 @@ raked_product(Layout<TShape,TStride> const& block,
|
||||
|
||||
auto result = logical_product(append<R>(block), append<R>(tiler));
|
||||
|
||||
return coalesce(zip(get<1>(result), get<0>(result)), tuple_repeat<R>(Int<1>{}));
|
||||
return zip(get<1>(result), get<0>(result));
|
||||
}
|
||||
|
||||
// tile_to_shape -- Perform a product of a layout so that the result matches a target shape.
|
||||
@@ -1742,7 +1742,7 @@ tile_to_shape(Layout<Shape,Stride> const& block,
|
||||
|
||||
auto product_shape = ceil_div(target_shape, block_shape);
|
||||
|
||||
return coalesce(blocked_product(padded_block, make_ordered_layout(product_shape, ord_shape)), product_shape);
|
||||
return blocked_product(padded_block, make_ordered_layout(product_shape, ord_shape));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user