1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
| template <typename Config> __global__ void smem_gemm_kernel(half_t* Dptr, const half_t* Aptr, const half_t* Bptr, int M, int N, int K) { using T = half_t; using SmemLayoutA = typename Config::SmemLayoutA; using SmemLayoutB = typename Config::SmemLayoutB; using TiledMMA = typename Config::MMA; using S2RCopyAtomA = typename Config::S2RCopyAtomA; using S2RCopyAtomB = typename Config::S2RCopyAtomB; using G2SCopyA = typename Config::G2SCopyA; using G2SCopyB = typename Config::G2SCopyB;
constexpr int kTileM = Config::kTileM; constexpr int kTileN = Config::kTileN; constexpr int kTileK = Config::kTileK;
extern __shared__ T shm_data[]; T* Ashm = shm_data; T* Bshm = shm_data + cosize(SmemLayoutA{});
int idx = threadIdx.x; int bx = blockIdx.x; int by = blockIdx.y;
auto A = make_tensor(make_gmem_ptr(Aptr), make_shape(M, K), make_stride(K, Int<1>{})); auto B = make_tensor(make_gmem_ptr(Bptr), make_shape(N, K), make_stride(K, Int<1>{})); auto D = make_tensor(make_gmem_ptr(Dptr), make_shape(M, N), make_stride(N, Int<1>{}));
auto gA = local_tile(A, make_tile(Int<kTileM>{}, Int<kTileK>{}), make_coord(by, _)); auto gB = local_tile(B, make_tile(Int<kTileN>{}, Int<kTileK>{}), make_coord(bx, _)); auto gD = local_tile(D, make_tile(Int<kTileM>{}, Int<kTileN>{}), make_coord(by, bx));
auto sA = make_tensor(make_smem_ptr(Ashm), SmemLayoutA{}); auto sB = make_tensor(make_smem_ptr(Bshm), SmemLayoutB{});
TiledMMA tiled_mma; auto thr_mma = tiled_mma.get_slice(idx); auto tCrA = thr_mma.partition_fragment_A(gA(_, _, 0)); auto tCrB = thr_mma.partition_fragment_B(gB(_, _, 0)); auto tCrD = thr_mma.partition_fragment_C(gD); clear(tCrD);
auto s2r_tiled_copy_a = make_tiled_copy_A(S2RCopyAtomA{}, tiled_mma); auto s2r_thr_copy_a = s2r_tiled_copy_a.get_slice(idx); auto tAsA = s2r_thr_copy_a.partition_S(sA); auto tCrA_view = s2r_thr_copy_a.retile_D(tCrA);
auto s2r_tiled_copy_b = make_tiled_copy_B(S2RCopyAtomB{}, tiled_mma); auto s2r_thr_copy_b = s2r_tiled_copy_b.get_slice(idx); auto tBsB = s2r_thr_copy_b.partition_S(sB); auto tCrB_view = s2r_thr_copy_b.retile_D(tCrB);
G2SCopyA g2s_tiled_copy_a; auto g2s_thr_copy_a = g2s_tiled_copy_a.get_slice(idx); auto tAgA_copy = g2s_thr_copy_a.partition_S(gA); auto tAsA_copy = g2s_thr_copy_a.partition_D(sA);
G2SCopyB g2s_tiled_copy_b; auto g2s_thr_copy_b = g2s_tiled_copy_b.get_slice(idx); auto tBgB_copy = g2s_thr_copy_b.partition_S(gB); auto tBsB_copy = g2s_thr_copy_b.partition_D(sB);
if (idx == 0 && bx == 0 && by == 0) { printf("\n === G2S Copy ===\n"); printf(" tAgA_copy shape: "); print(shape(tAgA_copy)); printf("\n"); printf(" tAgA_copy layout: "); print(tAgA_copy.layout()); printf("\n"); printf(" tAsA_copy shape: "); print(shape(tAsA_copy)); printf("\n"); printf(" tAsA_copy layout: "); print(tAsA_copy.layout()); printf("\n");
printf("\n === MMA fragment ===\n"); printf(" tCrA shape: "); print(shape(tCrA)); printf("\n"); printf(" tCrA layout: "); print(tCrA.layout()); printf("\n"); printf(" tCrB shape: "); print(shape(tCrB)); printf("\n"); printf(" tCrD shape: "); print(shape(tCrD)); printf("\n");
printf("\n === S2R Copy (make_tiled_copy_A) ===\n"); printf(" tAsA shape: "); print(shape(tAsA)); printf("\n"); printf(" tAsA layout: "); print(tAsA.layout()); printf("\n"); printf(" tCrA_view shape: "); print(shape(tCrA_view)); printf("\n"); printf(" tCrA_view layout: "); print(tCrA_view.layout()); printf("\n");
printf("\n === S2R Copy (make_tiled_copy_B) ===\n"); printf(" tBsB shape: "); print(shape(tBsB)); printf("\n"); printf(" tBsB layout: "); print(tBsB.layout()); printf("\n"); printf(" tCrB_view shape: "); print(shape(tCrB_view)); printf("\n"); printf(" tCrB_view layout: "); print(tCrB_view.layout()); printf("\n");
printf("\n === 循环结构 ===\n"); printf(" K 外层: K/kTileK = %d/%d = %d 轮\n", K, kTileK, K/kTileK); printf(" K 内层: nk = size<2>(tCrA) = %d 轮\n", int(size<2>(tCrA))); }
int num_tile_k = K / kTileK; for (int itile = 0; itile < num_tile_k; ++itile) { cute::copy(g2s_tiled_copy_a, tAgA_copy(_, _, _, itile), tAsA_copy(_, _, _)); cute::copy(g2s_tiled_copy_b, tBgB_copy(_, _, _, itile), tBsB_copy(_, _, _)); cp_async_fence(); cp_async_wait<0>(); __syncthreads();
int nk = size<2>(tCrA); for (int ik = 0; ik < nk; ++ik) { cute::copy(s2r_tiled_copy_a, tAsA(_, _, ik), tCrA_view(_, _, ik)); cute::copy(s2r_tiled_copy_b, tBsB(_, _, ik), tCrB_view(_, _, ik));
cute::gemm(tiled_mma, tCrD, tCrA(_, _, ik), tCrB(_, _, ik), tCrD); } __syncthreads(); }
auto tDgD = thr_mma.partition_C(gD); cute::copy(tCrD, tDgD); }
struct GemmConfig { using T = half_t; static constexpr int kTileM = 128; static constexpr int kTileN = 128; static constexpr int kTileK = 32;
using SmemLayoutAtom = decltype(composition( Swizzle<3, 3, 3>{}, make_layout(make_shape(Int<8>{}, Int<kTileK>{}), make_stride(Int<kTileK>{}, Int<1>{})))); using SmemLayoutA = decltype( tile_to_shape(SmemLayoutAtom{}, make_shape(Int<kTileM>{}, Int<kTileK>{}))); using SmemLayoutB = decltype( tile_to_shape(SmemLayoutAtom{}, make_shape(Int<kTileN>{}, Int<kTileK>{})));
using mma_op = SM80_16x8x16_F16F16F16F16_TN; using mma_atom = MMA_Atom<MMA_Traits<mma_op>>; using MMA = decltype(make_tiled_mma( mma_atom{}, make_layout(make_shape(Int<2>{}, Int<2>{}, Int<1>{})), Tile<Int<32>, Int<32>, Int<16>>{}));
using g2s_copy_op = SM80_CP_ASYNC_CACHEGLOBAL<cute::uint128_t>; using g2s_copy_atom = Copy_Atom<Copy_Traits<g2s_copy_op>, T>; using G2SCopyA = decltype(make_tiled_copy( g2s_copy_atom{}, make_layout(make_shape(Int<32>{}, Int<4>{}), make_stride(Int<4>{}, Int<1>{})), make_layout(make_shape(Int<1>{}, Int<8>{})))); using G2SCopyB = G2SCopyA;
using s2r_copy_atom = Copy_Atom<Copy_Traits<SM75_U32x4_LDSM_N>, T>; using S2RCopyAtomA = s2r_copy_atom; using S2RCopyAtomB = s2r_copy_atom;
static constexpr int kThreadNum = size(MMA{}); static constexpr int kShmSize = (cosize(SmemLayoutA{}) + cosize(SmemLayoutB{})) * sizeof(T); };
|