Two libraries, one API shape
cuBLAS and MPSMatrixMultiplication are different products from different companies but they implement essentially the same operation. The differences worth memorizing:
| Aspect | cuBLAS (NVIDIA) | MPS (Apple) |
|---|---|---|
| Layout default | Column-major (Fortran) | Row-major |
| Default precision focus | FP32, with FP16/BF16 via cublasGemmEx | Half-precision-first; FP32 also supported |
| Lifecycle | Handle per thread, async by default | Command buffer per dispatch, sync at waitUntilCompleted |
| α/β scalars | Yes (full GEMM signature) | Yes |
| Algorithm picker | Heuristic via cublasLt; manual via algo IDs | Library picks; less direct control |
Rules of the road for cuBLAS
- Create one
cublasHandle_tper thread (or per CUDA stream); reuse it across calls. - Async by default — call
cudaStreamSynchronizeif you need the result before the next CPU code. - Column-major math means most C/C++ users compute
Cᵀ = Bᵀ · AᵀviaCUBLAS_OP_Trather than transposing buffers.
Rules of the road for MPS
- Row-major by default; same direction your numpy / Swift arrays naturally store.
- Command buffer lifecycle is explicit: encode, commit, wait. The waiting step is non-optional.
- Half-precision
MPSMatrixis a first-class citizen — for inference, prefer FP16 unless numerical stability demands FP32.