v4.4 update. (#2979)
This commit is contained in:
@@ -51,8 +51,12 @@ template <class GmemTmaBasisStrides_, class TmaGmemBasis_, class TmaSwizzle_>
|
||||
struct AuxTmaParams {
|
||||
using GmemStrides = GmemTmaBasisStrides_; // Strides for Gmem mode -> Tma coord mode, may be dynamic
|
||||
GmemStrides g_stride_;
|
||||
using TmaGmemBasis = TmaGmemBasis_; // Layout for Tma box shape -> Gmem mode(s), always static
|
||||
static_assert(is_static<TmaGmemBasis>::value);
|
||||
using TmaGmemBasis = TmaGmemBasis_; // Layout for Tma box shape -> Gmem mode(s)
|
||||
// By default, TmaGmemBasis produced by construct_tma_gbasis is fully static.
|
||||
// The user may construct a dynamic gbasis manually (e.g. to represent smem box with dynamic shape).
|
||||
// In that case they will need to pass it around via other means.
|
||||
// We avoid passing it as a data member to avoid ABI impact.
|
||||
// static_assert(is_static<TmaGmemBasis>::value);
|
||||
using TmaSwizzle = TmaSwizzle_; // Tma swizzle, always Swizzle<B,M,S>
|
||||
static_assert(is_static<TmaSwizzle>::value);
|
||||
};
|
||||
@@ -70,7 +74,7 @@ struct TMA_LOAD_Unpack
|
||||
{
|
||||
static_assert(is_smem<TD>::value, "SM90_TMA_LOAD requires the destination be shared memory.");
|
||||
|
||||
auto src_coord = src.data().coord_;
|
||||
auto src_coord = src(Int<0>{});
|
||||
void* dst_ptr = cute::raw_pointer_cast(dst.data());
|
||||
#if 0
|
||||
auto [c0,c1,c2,c3,c4] = append<5>(src_coord, 0);
|
||||
@@ -237,7 +241,7 @@ struct Copy_Traits<SM90_TMA_LOAD::PREFETCH, NumBitsPerTMA, Args...>
|
||||
Tensor<TS,SLayout> const& src,
|
||||
Tensor<TD,DLayout> & dst)
|
||||
{
|
||||
auto src_coord = src.data().coord_;
|
||||
auto src_coord = src(Int<0>{});
|
||||
return detail::explode_tuple(detail::CallCOPY<SM90_TMA_LOAD::PREFETCH>{},
|
||||
traits.opargs_, tuple_seq<decltype(traits.opargs_)>{},
|
||||
src_coord, tuple_seq<decltype(src_coord)>{});
|
||||
@@ -405,7 +409,7 @@ struct Copy_Traits<SM90_TMA_STORE, NumBitsPerTMA, AuxParams_>
|
||||
|
||||
void const* const desc_ptr = &(traits.tma_desc_);
|
||||
void const* const src_ptr = cute::raw_pointer_cast(src.data());
|
||||
auto dst_coord = dst.data().coord_;
|
||||
auto dst_coord = dst(Int<0>{});
|
||||
#if 0
|
||||
auto [c0,c1,c2,c3,c4] = append<5>(dst_coord, 0);
|
||||
printf("THR (%d,%d,%d) BLK (%d,%d,%d) TMACRD (%d,%d,%d,%d,%d) SMEMADDR (%p)\n",
|
||||
@@ -446,7 +450,7 @@ struct Copy_Traits<SM90_TMA_STORE_PTR, NumBitsPerTMA>
|
||||
|
||||
void const* const desc_ptr = traits.tma_desc_;
|
||||
void const* const src_ptr = cute::raw_pointer_cast(src.data());
|
||||
auto dst_coord = dst.data().coord_;
|
||||
auto dst_coord = dst(Int<0>{});
|
||||
#if 0
|
||||
auto [c0,c1,c2,c3,c4] = append<5>(dst_coord, 0);
|
||||
printf("THR (%d,%d,%d) BLK (%d,%d,%d) TMACRD (%d,%d,%d,%d,%d) SMEMADDR (%p)\n",
|
||||
@@ -531,7 +535,8 @@ struct Copy_Traits<SM90_TMA_REDUCE_ADD, NumBitsPerTMA, AuxParams_>
|
||||
static_assert(is_smem<TS>::value, "Expected smem src for SM90_TMA_REDUCE_ADD");
|
||||
//static_assert(is_gmem<TD>::value, "Expected gmem dst for SM90_TMA_REDUCE_ADD"); // TMA spoofed src tensor
|
||||
|
||||
traits.copy_unpack_(cute::raw_pointer_cast(src.data()), dst.data().coord_, tuple_seq<decltype(dst.data().coord_)>{});
|
||||
auto dst_coord = dst(Int<0>{});
|
||||
traits.copy_unpack_(cute::raw_pointer_cast(src.data()), dst_coord, tuple_seq<decltype(dst_coord)>{});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1353,6 +1353,186 @@ struct MMA_Traits<SM100_MMA_F16BF16_SS_SCALED<a_type, b_type, c_type,
|
||||
with(UMMA::ScaleOut accumulate, cute::integral_constant<uint32_t, NewScaleC> scaleC) const {
|
||||
return {accumulate, idesc_};
|
||||
}
|
||||
|
||||
template <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<a_type, b_type, c_type, M, N, a_major, b_major, new_a_neg, b_neg>()};
|
||||
}
|
||||
};
|
||||
|
||||
// Special instantiation for interleaved complex (emulated)
|
||||
template <class ab_vtype, 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<cutlass::complex<ab_vtype>, cutlass::complex<ab_vtype>, float,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg>>
|
||||
{
|
||||
static_assert(cute::sizeof_bits_v<ab_vtype> == 16, "Only supports 16bit base types");
|
||||
using a_type = complex<ab_vtype>;
|
||||
using b_type = complex<ab_vtype>;
|
||||
using c_type = float;
|
||||
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
|
||||
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<
|
||||
ab_vtype, ab_vtype, float, 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 <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<ab_vtype, ab_vtype, float, M, N, a_major, b_major, new_a_neg, b_neg>()};
|
||||
}
|
||||
};
|
||||
|
||||
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_TF32_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> == 32, "SM100_MMA_TF32_TS_SCALED supports 32bit 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_TF32_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_TF32_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 <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_TF32_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg, c_sat>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<a_type, b_type, c_type, M, N, a_major, b_major, new_a_neg, b_neg, c_sat>()};
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
@@ -1427,8 +1607,105 @@ struct MMA_Traits<SM100_MMA_F16BF16_TS_SCALED<a_type, b_type, c_type,
|
||||
with(UMMA::ScaleOut accumulate, cute::integral_constant<uint32_t, NewScaleC> scaleC) const {
|
||||
return {accumulate, idesc_};
|
||||
}
|
||||
|
||||
template <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg, c_sat>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<a_type, b_type, c_type, M, N, a_major, b_major, new_a_neg, b_neg, c_sat>()};
|
||||
}
|
||||
};
|
||||
|
||||
// Special instantiation for interleaved complex (emulated)
|
||||
template <class ab_vtype, 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<cutlass::complex<ab_vtype>, cutlass::complex<ab_vtype>, float,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg, c_sat>>
|
||||
{
|
||||
static_assert(cute::sizeof_bits_v<ab_vtype> == 16, "Only supports 16bit base types");
|
||||
using a_type = complex<ab_vtype>;
|
||||
using b_type = complex<ab_vtype>;
|
||||
using c_type = float;
|
||||
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
|
||||
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<
|
||||
ab_vtype, ab_vtype, float, 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 <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg, c_sat>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<ab_vtype, ab_vtype, float, M, N, a_major, b_major, new_a_neg, b_neg, c_sat>()};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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 b_neg,
|
||||
@@ -1605,6 +1882,82 @@ struct MMA_Traits<SM100_MMA_F16BF16_SS_SPARSE<a_type, b_type, c_type,
|
||||
}
|
||||
};
|
||||
|
||||
template <int M, int N, UMMA::Major a_major, UMMA::Major b_major,
|
||||
UMMA::ScaleIn a_neg, UMMA::ScaleIn b_neg,
|
||||
UMMA::Saturate c_sat>
|
||||
struct MMA_Traits<SM100_MMA_TF32_TS_INTERLEAVED_CF32CTF32CTF32CF32_TN<
|
||||
M, N,
|
||||
a_major, b_major,
|
||||
a_neg, b_neg, c_sat>>
|
||||
{
|
||||
using a_type = complex<tfloat32_t>;
|
||||
using b_type = complex<tfloat32_t>;
|
||||
using c_type = float;
|
||||
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
// MMA based interleaved complex GEMM calculates realAcc and imagAcc separately.
|
||||
// This MMA_traits is used to calculate 1 of the GEMMs below :
|
||||
// 1. realAcc = realA * realB + (-imagA) * imagB
|
||||
// 2. imagAcc = imagA * realB + realA * imagB
|
||||
// So it requires complex<tfloat32_t> type operand A&B and float type operand Acc.
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_TF32_TS_INTERLEAVED_CF32CTF32CTF32CF32_TN A from TMEM can't be transposed");
|
||||
static_assert(b_major == UMMA::Major::K, "SM100_MMA_TF32_TS_INTERLEAVED_CF32CTF32CTF32CF32_TN B from SMEM requires non-transpose");
|
||||
|
||||
UMMA::InstrDescriptor idesc_ = UMMA::make_instr_desc<
|
||||
tfloat32_t, tfloat32_t, float, 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_TF32_TS_INTERLEAVED_CF32CTF32CTF32CF32_TN<
|
||||
M, N,
|
||||
a_major, b_major,
|
||||
a_neg, b_neg, c_sat>::fma(tmem_a, desc_b, tmem_c, uint32_t(traits.accumulate_), idesc);
|
||||
}
|
||||
};
|
||||
|
||||
template <class a_type, class b_type, class c_type,
|
||||
int M, int N,
|
||||
UMMA::Major a_major, UMMA::Major b_major,
|
||||
@@ -1938,8 +2291,187 @@ struct MMA_Traits<SM100_MMA_F16BF16_2x1SM_SS_SCALED<a_type, b_type, c_type,
|
||||
with(UMMA::ScaleOut accumulate, cute::integral_constant<uint32_t, NewScaleC> scaleC) const {
|
||||
return {accumulate, idesc_};
|
||||
}
|
||||
|
||||
template <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_2x1SM_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<a_type, b_type, c_type, M, N, a_major, b_major, new_a_neg, b_neg>()};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Special instantiation for interleaved complex (emulated)
|
||||
template <class ab_vtype, 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<cutlass::complex<ab_vtype>, cutlass::complex<ab_vtype>, float,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg>>
|
||||
{
|
||||
static_assert(cute::sizeof_bits_v<ab_vtype> == 16, "Only supports 16bit base types");
|
||||
using a_type = complex<ab_vtype>;
|
||||
using b_type = complex<ab_vtype>;
|
||||
using c_type = float;
|
||||
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
|
||||
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<
|
||||
ab_vtype, ab_vtype, float, 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 <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_2x1SM_SS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<ab_vtype, ab_vtype, float, M, N, a_major, b_major, new_a_neg, b_neg>()};
|
||||
}
|
||||
};
|
||||
|
||||
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_TF32_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> == 32, "SM100_MMA_TF32_2x1SM_TS_SCALED supports 32bit 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_TF32_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_TF32_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 <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_TF32_2x1SM_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg, c_sat>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<a_type, b_type, c_type, M, N, a_major, b_major, new_a_neg, b_neg, c_sat>()};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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>
|
||||
@@ -2011,8 +2543,105 @@ struct MMA_Traits<SM100_MMA_F16BF16_2x1SM_TS_SCALED<a_type, b_type, c_type,
|
||||
with(UMMA::ScaleOut accumulate, cute::integral_constant<uint32_t, NewScaleC> scaleC) const {
|
||||
return {accumulate, idesc_};
|
||||
}
|
||||
|
||||
template <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_2x1SM_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg, c_sat>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<a_type, b_type, c_type, M, N, a_major, b_major, new_a_neg, b_neg, c_sat>()};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Special instantiation for interleaved complex (emulated)
|
||||
template <class ab_vtype, 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<cutlass::complex<ab_vtype>, cutlass::complex<ab_vtype>, float,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, a_neg, b_neg, c_sat>>
|
||||
{
|
||||
static_assert(cute::sizeof_bits_v<ab_vtype> == 16, "Only supports 16bit base types");
|
||||
using a_type = complex<ab_vtype>;
|
||||
using b_type = complex<ab_vtype>;
|
||||
using c_type = float;
|
||||
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
|
||||
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<
|
||||
ab_vtype, ab_vtype, float, 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 <UMMA::ScaleIn new_a_neg>
|
||||
CUTE_HOST_DEVICE constexpr
|
||||
MMA_Traits<SM100_MMA_F16BF16_2x1SM_TS_SCALED<a_type, b_type, c_type,
|
||||
M, N, a_major, b_major,
|
||||
ScaleC, new_a_neg, b_neg, c_sat>>
|
||||
with(cute::integral_constant<UMMA::ScaleIn, new_a_neg>) const {
|
||||
return {accumulate_, UMMA::make_instr_desc<ab_vtype, ab_vtype, float, M, N, a_major, b_major, new_a_neg, b_neg, c_sat>()};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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 b_neg,
|
||||
@@ -2189,6 +2818,82 @@ struct MMA_Traits<SM100_MMA_F16BF16_2x1SM_SS_SPARSE<a_type, b_type, c_type,
|
||||
}
|
||||
};
|
||||
|
||||
template <int M, int N, UMMA::Major a_major, UMMA::Major b_major,
|
||||
UMMA::ScaleIn a_neg, UMMA::ScaleIn b_neg,
|
||||
UMMA::Saturate c_sat>
|
||||
struct MMA_Traits<SM100_MMA_TF32_2x1SM_TS_INTERLEAVED_CF32CTF32CTF32CF32_TN<
|
||||
M, N,
|
||||
a_major, b_major,
|
||||
a_neg, b_neg, c_sat>>
|
||||
{
|
||||
using a_type = complex<tfloat32_t>;
|
||||
using b_type = complex<tfloat32_t>;
|
||||
using c_type = float;
|
||||
|
||||
using ValTypeD = c_type;
|
||||
using ValTypeA = a_type;
|
||||
using ValTypeB = b_type;
|
||||
using ValTypeC = c_type;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
// Interleaved complex GEMM calculates realAcc and imagAcc separately.
|
||||
// This MMA_traits is used to calculate 1 of the GEMMs below :
|
||||
// 1. realAcc = realA * realB + (-imagA) * imagB
|
||||
// 2. imagAcc = imagA * realB + realA * imagB
|
||||
// So it requires complex<tfloat32_t> type operand A&B and float type operand Acc.
|
||||
static_assert(a_major == UMMA::Major::K, "SM100_MMA_TF32_2x1SM_TS_INTERLEAVED_CF32CTF32CTF32CF32_TN A from TMEM can't be transposed");
|
||||
static_assert(b_major == UMMA::Major::K, "SM100_MMA_TF32_2x1SM_TS_INTERLEAVED_CF32CTF32CTF32CF32_TN B from SMEM requires non-transpose");
|
||||
|
||||
UMMA::InstrDescriptor idesc_ = UMMA::make_instr_desc<
|
||||
tfloat32_t, tfloat32_t, float, 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_TF32_2x1SM_TS_INTERLEAVED_CF32CTF32CTF32CF32_TN<
|
||||
M, N,
|
||||
a_major, b_major,
|
||||
a_neg, b_neg, c_sat>::fma(tmem_a, desc_b, tmem_c, uint32_t(traits.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>
|
||||
@@ -2640,7 +3345,7 @@ struct MMA_Traits<SM100_MMA_F8F6F4_SS, a_type, b_type, c_type,
|
||||
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(((b_major == UMMA::Major::K) && ((N % 8 == 0) && (8 <= N) && (N <= 256))) ||
|
||||
((b_major == UMMA::Major::MN) && ((N % 16 == 0) && (16 <= N) && (N <= 256))),
|
||||
((b_major == UMMA::Major::MN) && ((N % 16 == 0) && (16 <= N) && (N <= 256))),
|
||||
"SM100_MMA_F8F6F4_SS N-mode size should be a multiple of 8 between 8 and 256 when B is K major. \
|
||||
SM100_MMA_F8F6F4_SS N-mode size should be a multiple of 16 between 16 and 256 when B is MN major.");
|
||||
using FrgTypeA = UMMA::smem_desc<a_major>;
|
||||
@@ -3058,7 +3763,7 @@ struct MMA_Traits<SM100_MMA_F8F6F4_2x1SM_SS, a_type, b_type, c_type,
|
||||
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(((b_major == UMMA::Major::K) && ((N % 16 == 0) && (16 <= N) && (N <= 256))) ||
|
||||
((b_major == UMMA::Major::MN) && ((N % 32 == 0) && (32 <= N) && (N <= 256))),
|
||||
((b_major == UMMA::Major::MN) && ((N % 32 == 0) && (32 <= N) && (N <= 256))),
|
||||
"SM100_MMA_F8F6F4_2x1SM_SS N-mode size should be a multiple of 16 between 16 and 256 when B is K major. \
|
||||
SM100_MMA_F8F6F4_2x1SM_SS N-mode size should be a multiple of 32 between 32 and 256 when B is MN major.");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user