OpenGEMM
GEMM kernels for NVIDIA B200 (sm_100a) in CUDA.
import opengemm as og
c = og.gemm(a, b) # C[M, N] = A[M, K] @ B[N, K].T
c = og.gemm(a, b, sfa, sfb) # block-scaled: nvfp4, mxfp8, mxfp4
og.emit_kernel(a, b, file="k.cu") # emits .cu/.cuh for this shape
c = og.run_kernel("k.cu", a, b) # compiles emitted kernel and runs it
Install
From PyPI
pip install opengemm
From a clone:
git clone https://github.com/aramesh10/OpenGEMM.git
cd OpenGEMM
pip install -e .
Requirements:
- sm_100a
- CUDA 12.9+ with
nvccon the path - PyTorch 2.8+.
The first gemm() call builds the extension (a few minutes, then cached by torch).
Agent Quickstart
Give your agent this prompt to use OpenGEMM as a tool:
OpenGEMM emits standalone CUDA GEMM kernels for B200 (sm_100a), no GPU
needed to emit:
python -c "
import opengemm as og
S = dict(m=1024, n=1024, k=1024)
og.emit_kernel(**S, atype='bf16', file='k') # writes k.cu and k.cuh
og.emit_kernel(**S, atype='e4m3', btype='e5m2') # mixed, names itself
og.emit_kernel(**S, atype='e2m1', sftype='ue4m3') # block-scaled (nvfp4)
src, hdr = og.emit_kernel(**S, atype='bf16') # the text, always returned
print(src, hdr)
"
atype / btype: bf16 f16 tf32 s8 u8 e4m3 e5m2 e3m2 e2m3 e2m1
sftype (block-scaled): ue4m3 (nvfp4) or ue8m0 (mxfp8, mxfp4)
dtype (output): f32, s32 for s8/u8, bf16 when scaled — inferred, optional.
Dense and block-scaled
C[M, N] = A[M, K] @ B[N, K].T. Both operands are row-major with K innermost.
| GEMM | atype / btype |
sftype |
dtype |
torch.dtype (in → out) |
|---|---|---|---|---|
| bfloat16 | bf16 | — | f32 | bfloat16 → float32 |
| float16 | f16 | — | f32 | float16 → float32 |
| tf32 | tf32 | — | f32 | float32 → float32 |
| int8 | s8 | — | s32 | int8 → int32 |
| uint8 | u8 | — | s32 | uint8 → int32 |
| fp8 | e4m3 | — | f32 | float8_e4m3fn → float32 |
| fp8 | e5m2 | — | f32 | float8_e5m2 → float32 |
| mixed fp8 | e4m3, e5m2 | — | f32 | float8_e4m3fn, float8_e5m2 → float32 |
| fp6 | e3m2 | — | f32 | uint8 → float32 |
| fp6 | e2m3 | — | f32 | uint8 → float32 |
| fp4 | e2m1 | — | f32 | uint8 → float32 |
| nvfp4 | e2m1 | ue4m3 (per 16) | bf16 | float4_e2m1fn_x2, float8_e4m3fn → bfloat16 |
| mxfp8 | e4m3 | ue8m0 (per 32) | bf16 | float8_e4m3fn, float8_e8m0fnu → bfloat16 |
| mxfp4 | e2m1 | ue8m0 (per 32) | bf16 | float4_e2m1fn_x2, float8_e8m0fnu → bfloat16 |
Note: fp6 and fp4 have no torch dtype. They arrive densely packed in uint8 and are named - gemm(a, b, atype="e2m1")
Use btype= when the two operands differ.
Input is [M, K] and [N, K] with column-major strides (1, M) and (1, N)
Output is [M, N] with column-major strides (1, M)
Tuning and performance
There is no heursitic to choose the config. Optimized configs are stored in configs.json.
If a particular shape has not been optimized, the library autotunes and returns and saves the best config locally to ./opengemm-configs/tuned_configs.json or to OPENGEMM_CONFIGS env variable.
CUDA_VISIBLE_DEVICES=0 python scripts/tune.py --dtype f16 --shape 4096 4096 4096
CUDA_VISIBLE_DEVICES=0 python scripts/benchmark.py --dtype bf16 e4m3 # vs cuBLAS
CUDA_VISIBLE_DEVICES=0 python scripts/test.py # correctness
tune.py ablates every compiled configuration for a shape and records the best performing config to configs.json
Standalone kernels
python scripts/emit_kernel.py --dtype e4m3 --shape 4096 4096 4096 --file emitted/e4m3_4k.cu
python scripts/run_kernel.py emitted/e4m3_4k.cu # correctness, then timing vs cuBLAS
OpenGEMM can also emit the optimized CUDA files for a kernel given a shape and dtype. It can be ran with scripts/run_kernel.py or built with nvcc:
nvcc -O3 -std=c++20 -gencode=arch=compute_100a,code=sm_100a --expt-relaxed-constexpr -shared -Xcompiler -fPIC -lcuda <KERNEL_FILE>.cu -o <KERNEL_FILE>.so
emit_kernel reads only shapes and dtypes, so meta tensors work:
emit_kernel(torch.empty(4096, 4096, dtype=torch.bfloat16, device="meta"), ...).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file opengemm-0.1.0.tar.gz.
File metadata
- Download URL: opengemm-0.1.0.tar.gz
- Upload date:
- Size: 87.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b532c9618d12eadef6bf7a6be8839b5e1f0c9373c02f64b4388a8c727473e4ce
|
|
| MD5 |
0f380f3e843218956e0ecf1d4ab74eee
|
|
| BLAKE2b-256 |
7c964f65b3e39b6d344f910f187443217961ff5e528627329ca2f88a08897172
|
File details
Details for the file opengemm-0.1.0-py3-none-any.whl.
File metadata
- Download URL: opengemm-0.1.0-py3-none-any.whl
- Upload date:
- Size: 92.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7062ab87bf409b715a7fa1cffa5066efd0d3e7bd0aa5fb866aad79dd0034eca8
|
|
| MD5 |
8f1aaac2ab0826c94f689c9e02b61aca
|
|
| BLAKE2b-256 |
1c94956f7b87a9b2a5aeb0c809b7af94a97f8a27b2eec3050cfba098e6e5f6b2
|