Files
project_6/cat_files/edtallison_03_kernel_shared_mem_blocking.cuh
dylan 7cfa87b5ac data: cat SGEMM files from 3 repos into cat_files/
siboehm/SGEMM_CUDA (19 files):
  siboehm_sgemm.cu, siboehm_runner.cu, siboehm_runner.cuh, siboehm_kernels.cuh
  siboehm_cuBLAS_sgemm.cu, siboehm_simplest_kernel.cu, siboehm_CMakeLists.txt
  siboehm_{1_naive..12_kernel_double_buffering}.cuh

wangzyon/NVIDIA_SGEMM_PRACTICE (12 files):
  wangzyon_sgemm.cu, wangzyon_utils.cu, wangzyon_utils.cuh, wangzyon_kernel.cuh
  wangzyon_CMakeLists.txt, wangzyon_kernel_{1..7}.cuh

edtallison/sgemm-cuda (19 files):
  edtallison_sgemm.cu, edtallison_runner.cu, edtallison_runner.cuh
  edtallison_kernels.cuh, edtallison_cuBLAS_sgemm.cu, edtallison_simplest_kernel.cu
  edtallison_CMakeLists.txt, edtallison_{01_naive..12_kernel_double_buffering}.cuh

cat_files/ total: 25 → 75 files
2026-08-15 06:59:18 +00:00

54 lines
2.3 KiB
Plaintext

#pragma once
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cublas_v2.h>
#include <cuda_runtime.h>
#define CEIL_DIV(M, N) (((M) + (N)-1) / (N))
template <const int BLOCKSIZE>
__global__ void sgemm_shared_mem_block(int M, int N, int K, float alpha,
const float *A, const float *B,
float beta, float *C) {
// output C block we want to compute with this threadBlock
const uint cRow = blockIdx.x;
const uint cCol = blockIdx.y;
// allocate buffer for current block in fast SMEM (shared between all threads in block)
__shared__ float As[BLOCKSIZE * BLOCKSIZE];
__shared__ float Bs[BLOCKSIZE * BLOCKSIZE];
// the inner row and col that we are accessing in this specific thread
const uint threadRow = threadIdx.x / BLOCKSIZE; // note similarity to previous kernel
const uint threadCol = threadIdx.x % BLOCKSIZE;
// advance pointers to the starting positions (they are input as pointers to first elements in the matrices)
A += cRow * BLOCKSIZE * K; // row=cRow, col=0 (the start of the relevant row)
B += cCol * BLOCKSIZE; // row=0, col=cCol (top of relevant col)
C += cRow * BLOCKSIZE * N + cCol * BLOCKSIZE; // row=cRow, col=cCol
float tmp = 0.0;
for (int bkIdx=0; bkIdx < K; bkIdx+=BLOCKSIZE) { // shifting the whole block along the row of A and col of B
// have each thread load one of the elements in A and B
// make the threadCol (=threadIdx.x) the consecutive index
// to allow GMEM access coalescing
As[threadRow * BLOCKSIZE + threadCol] = A[threadRow * K + threadCol];
Bs[threadRow * BLOCKSIZE + threadCol] = B[threadRow * N + threadCol];
// ensure cache is fully populated
__syncthreads();
A += BLOCKSIZE; // for next iteration
B += BLOCKSIZE * N;
// execute the dotproduct on the currently cached block
for (int dotIdx = 0; dotIdx < BLOCKSIZE; ++dotIdx) {
tmp += As[threadRow * BLOCKSIZE + dotIdx] *
Bs[dotIdx * BLOCKSIZE + threadCol];
}
// sync so faster threads don't fetch the next block into cache
_syncthreads();
}
C[threadRow * N + threadCol] = alpha * tmp + beta * C[threadRow * N + threadCol];
}