|
|
|
|
|
|
|
|
| #include <cuda_fp16.h>
|
| #include <mma.h>
|
| #include <stdio.h>
|
|
|
| using namespace nvcuda;
|
|
|
|
|
| #define WGSIZE_M 128
|
| #define WGSIZE_N 128
|
| #define WGSIZE_K 32
|
| #define WARP_M 32
|
| #define WARP_N 64
|
| #define MMA_M 16
|
| #define MMA_N 8
|
| #define MMA_K 8
|
|
|
|
|
| __shared__ __half smem_a[2][WGSIZE_K][WGSIZE_M];
|
| __shared__ __half smem_b[2][WGSIZE_K][WGSIZE_N];
|
|
|
| extern "C" __global__ void pax_gemm_sm86(
|
| const __half* __restrict__ A,
|
| const __half* __restrict__ B,
|
| float* __restrict__ C,
|
| int M, int N, int K
|
| ) {
|
|
|
| int warp_id = (threadIdx.x + threadIdx.y * blockDim.x) / 32;
|
| int warp_row = warp_id / (WGSIZE_N / WARP_N);
|
| int warp_col = warp_id % (WGSIZE_N / WARP_N);
|
|
|
| int block_row = blockIdx.y * WGSIZE_M + warp_row * WARP_M;
|
| int block_col = blockIdx.x * WGSIZE_N + warp_col * WARP_N;
|
|
|
|
|
| wmma::fragment<wmma::accumulator, MMA_M, MMA_N, MMA_K, float>
|
| c_frag[WARP_M / MMA_M][WARP_N / MMA_N];
|
| for (int i = 0; i < WARP_M / MMA_M; i++)
|
| for (int j = 0; j < WARP_N / MMA_N; j++)
|
| wmma::fill_fragment(c_frag[i][j], 0.0f);
|
|
|
|
|
| int buf = 0;
|
|
|
|
|
| asm volatile("cp.async.ca.shared.global [%0], [%1], 32;\n"
|
| : : "r"((unsigned)__cvta_generic_to_shared(&smem_a[buf][0][0])),
|
| "l"(A));
|
| asm volatile("cp.async.ca.shared.global [%0], [%1], 32;\n"
|
| : : "r"((unsigned)__cvta_generic_to_shared(&smem_b[buf][0][0])),
|
| "l"(B));
|
| asm volatile("cp.async.commit_group;\n");
|
|
|
| for (int k = 0; k < K; k += WGSIZE_K) {
|
|
|
| asm volatile("cp.async.wait_group 0;\n");
|
| __syncthreads();
|
|
|
|
|
| wmma::fragment<wmma::matrix_a, MMA_M, MMA_N, MMA_K, __half, wmma::row_major> a_frag;
|
| wmma::fragment<wmma::matrix_b, MMA_M, MMA_N, MMA_K, __half, wmma::col_major> b_frag;
|
|
|
|
|
| for (int i = 0; i < WARP_M / MMA_M; i++) {
|
| wmma::load_matrix_sync(a_frag, &smem_a[buf][0][warp_row * WARP_M + i * MMA_M], WGSIZE_M);
|
| for (int j = 0; j < WARP_N / MMA_N; j++) {
|
| wmma::load_matrix_sync(b_frag, &smem_b[buf][0][warp_col * WARP_N + j * MMA_N], WGSIZE_N);
|
|
|
| wmma::mma_sync(c_frag[i][j], a_frag, b_frag, c_frag[i][j]);
|
| }
|
| }
|
|
|
| buf ^= 1;
|
|
|
|
|
| if (k + WGSIZE_K < K) {
|
| asm volatile("cp.async.ca.shared.global [%0], [%1], 32;\n"
|
| : : "r"((unsigned)__cvta_generic_to_shared(&smem_a[buf][0][0])),
|
| "l"(A + (k + WGSIZE_K) * M));
|
| asm volatile("cp.async.ca.shared.global [%0], [%1], 32;\n"
|
| : : "r"((unsigned)__cvta_generic_to_shared(&smem_b[buf][0][0])),
|
| "l"(B + (k + WGSIZE_K) * N));
|
| asm volatile("cp.async.commit_group;\n");
|
| }
|
| }
|
|
|
|
|
| for (int i = 0; i < WARP_M / MMA_M; i++) {
|
| for (int j = 0; j < WARP_N / MMA_N; j++) {
|
| int out_row = block_row + i * MMA_M;
|
| int out_col = block_col + j * MMA_N;
|
| if (out_row < M && out_col < N)
|
| wmma::store_matrix_sync(
|
| C + out_row * N + out_col,
|
| c_frag[i][j],
|
| N,
|
| wmma::mem_row_major
|
| );
|
| }
|
| }
|
| }
|
|
|