GEMM (General Matrix Multiplication) is the operation behind every
layer of a neural network: every linear layer, attention
projection, and fully-connected layer eventually reduces to it.
This project builds a CUDA implementation of GEMM from first
steps: starting from a naive, one-thread-per-output kernel,
profiling it with Nsight Compute to find the exact bottleneck,
and then rebuilding it with shared-memory tiling.
The tile size (TILE_WIDTH=16 vs. 32) was not guessed.It
was decided using Nsight-measured Duration, occupancy, and DRAM
bandwidth data.
Shared-memory access patterns were checked for bank conflicts at
both sizes (zero found at either).
The final kernel is wrapped with pybind11 so it is directly
callable from Python on NumPy arrays, and cross-validated for
identical output correctness against a CPU reference and
PyTorch/cuBLAS across five matrix sizes.
At 4096×4096, the kernel reaches
932.9 GFLOPS which is about 11.5% of the T4's FP32 hardware
peak, and roughly 26% of PyTorch/cuBLAS's measured throughput on
the same hardware.
That remaining gap comes from register blocking, double buffering,
and hand-tuned instruction scheduling that cuBLAS has and this
kernel doesn't which the next layer i'm trying to close.