diff --git a/.github/scripts/build-rocm.sh b/.github/scripts/build-rocm.sh
index 5f507efce..7f971824a 100644
--- a/.github/scripts/build-rocm.sh
+++ b/.github/scripts/build-rocm.sh
@@ -40,6 +40,11 @@ if rocm_version_at_least "7.14"; then
bnb_rocm_arch="${bnb_rocm_arch};gfx908;gfx1030;gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036"
fi
+# ROCm 7.14+ - Add CDNA5 (gfx1250).
+if rocm_version_at_least "7.14"; then
+ bnb_rocm_arch="${bnb_rocm_arch};gfx1250"
+fi
+
if [ "${RUNNER_OS}" == "Linux" ]; then
image_suffix="complete"
if rocm_version_at_least "7.14"; then
diff --git a/README.md b/README.md
index 4aef60d4b..5d7f2240b 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ bitsandbytes has the following minimum requirements for all platforms:
|
🟥 AMD GPU
cuda |
- CDNA: gfx908, gfx90a, gfx942, gfx950
+ CDNA: gfx908, gfx90a, gfx942, gfx950, gfx1250
RDNA: gfx103X, gfx110X, gfx115X, gfx120X
|
✅ |
diff --git a/bitsandbytes/backends/cuda/ops.py b/bitsandbytes/backends/cuda/ops.py
index 0d288d82b..1f3ce82e0 100644
--- a/bitsandbytes/backends/cuda/ops.py
+++ b/bitsandbytes/backends/cuda/ops.py
@@ -807,18 +807,21 @@ def _gemm_4bit_use_custom_rocm(device_index, dtype, M, N, K):
Fused SIMT kernel vs dequant+F.linear heuristic for ROCm.
RDNA3/RDNA4 calibration keeps the SIMT kernel through ~M=8.
+ gfx125x (CDNA5) is Wave32 but lacks the v_dot2 SIMT
+ instructions, so its kernel takes the fp32-FMA CDNA math path. The crossover
+ below is left at the gfx12 default (M<=8) pending dedicated calibration.
CDNA/gfx9 is calibrated on MI308X (gfx942): bf16/fp16 win through M<=4
after the SIMT math-path tuning, while fp32 only has a broad win through M<=2.
- TODO: revisit once WMMA/MFMA kernels land.
+ TODO: revisit once WMMA/MFMA kernels land; calibrate the gfx125x crossover.
"""
if M <= _GEMM_4BIT_CUSTOM_FLOOR_M and dtype != torch.float32:
return True
arch = _rocm_gfx_arch(device_index)
- if arch.startswith("gfx11") or arch.startswith("gfx12"): # RDNA3 / RDNA4
+ if arch.startswith("gfx11") or arch.startswith("gfx12"): # RDNA3 / RDNA4 / CDNA5 (gfx125x)
return M <= 8
- if arch.startswith("gfx9"): # CDNA / MI-series
+ if arch.startswith("gfx9"): # CDNA1-4 / MI-series (Wave64)
return M <= (2 if dtype == torch.float32 else 4)
return M <= 4 # unknown ROCm arch: conservative tiny-batch floor
diff --git a/csrc/common.cuh b/csrc/common.cuh
index 9df046903..503870124 100644
--- a/csrc/common.cuh
+++ b/csrc/common.cuh
@@ -20,6 +20,14 @@
#define IS_CDNA4 (defined(__gfx950__))
#define IS_CDNA (IS_CDNA1 || IS_CDNA2 || IS_CDNA3 || IS_CDNA4)
+// CDNA5 (gfx1250, gfx1251). Unlike the Wave64 CDNA1-4, CDNA5
+// runs in Wave32 mode. It is deliberately kept OUT of IS_CDNA (which implies
+// Wave64) so the default warp size below already resolves to 32 for it, unchanged
+// from upstream. It is detected separately only so the 4-bit GEMM can opt into
+// the CDNA fp32-FMA math path -- CDNA5 has no SIMT v_dot2 instruction (no
+// dot12-insts).
+#define IS_CDNA5 (defined(__gfx1250__) || defined(__gfx1251__))
+
// Warp size
#if BNB_HIP
diff --git a/csrc/gemm_4bit_simt.cu b/csrc/gemm_4bit_simt.cu
index c0062c4f9..d0f5354fb 100644
--- a/csrc/gemm_4bit_simt.cu
+++ b/csrc/gemm_4bit_simt.cu
@@ -8,12 +8,16 @@
#include "gemm_4bit_common.cuh"
#include "gemm_4bit_simt.cuh"
-#if IS_CDNA
-// gfx9/CDNA tuning:
+// gfx9/CDNA tuning (CDNA1-4 and CDNA5/gfx1250):
// - use fmaf for fp32 accumulation
// - accumulate fp16/bf16 pairs in fp32 via fused multiply-add
// - keep 16-bit centroids unscaled and fold scale into the fp32 accumulator
// - use packed fp16 accumulation
+// CDNA5 (gfx1250) is Wave32, but it does NOT implement the SIMT dot instructions
+// (no dot12-insts / v_dot2_f32_* builtins), so it opts into this fp32-FMA path
+// rather than the v_dot2 path below. This improves bf16/fp16 accuracy relative
+// to the generic fallback.
+#if IS_CDNA || IS_CDNA5
#define BNB_SIMT_F32_FMAF 1
#define BNB_SIMT_16BIT_FLOAT_FMA 1
#define BNB_SIMT_BF16_UNSCALED_CENTROID 1
@@ -28,7 +32,11 @@
#endif
// RDNA3/RDNA3.5/RDNA4 tuning:
-// - use native packed bf16/fp16 dot2 instructions with fp32 accumulation
+// - use native packed bf16/fp16 dot2 instructions with fp32 accumulation.
+// Note: CDNA5 (gfx1250) is intentionally excluded here. Despite its gfx12xx
+// target number, it lacks the dot12-insts v_dot2_f32_bf16 / v_dot2_f32_f16
+// builtins (they fail to compile for gfx1250), so it uses the fp32-FMA CDNA path
+// above.
#if IS_RDNA3 || IS_RDNA3_5 || IS_RDNA4
#define BNB_HIP_BF16_VDOT2 1
#define BNB_HIP_FP16_DOT2 1
diff --git a/docs/source/installation.mdx b/docs/source/installation.mdx
index 86d50ec80..3ee3c5754 100644
--- a/docs/source/installation.mdx
+++ b/docs/source/installation.mdx
@@ -146,7 +146,7 @@ The currently distributed `bitsandbytes` are built with the following configurat
| **Linux x86-64** | 7.0.2 | CDNA: gfx90a, gfx942, gfx950 / RDNA: gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx1153, gfx1200, gfx1201
| **Linux x86-64** | 7.1.1 | CDNA: gfx90a, gfx942, gfx950 / RDNA: gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx1153, gfx1200, gfx1201
| **Linux x86-64** | 7.2.4 | CDNA: gfx90a, gfx942, gfx950 / RDNA: gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx1153, gfx1200, gfx1201
-| **Linux x86-64** | 7.14.0 | CDNA: gfx908, gfx90a, gfx942, gfx950 / RDNA: gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx1153, gfx1200, gfx1201
+| **Linux x86-64** | 7.14.0 | CDNA: gfx908, gfx90a, gfx942, gfx950, gfx1250 / RDNA: gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx1153, gfx1200, gfx1201
| **Windows x86-64** | 7.2.1 | RDNA: gfx1100, gfx1101, gfx1102, gfx1150, gfx1151, gfx1200, gfx1201
| **Windows x86-64** | 7.14.0 | RDNA: gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1150, gfx1151, gfx1152, gfx1153, gfx1200, gfx1201