char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

thelittlefiremanggml-cuda: fallback to F32 on device without BF16 hardware acceleration (#28846)ad6c66839

char/aliceai-t5-moe
63.8 KiB1717 linesraw
1#pragma once
2
3#include "ggml.h"
4#include "ggml-impl.h"
5#include "ggml-cuda.h"
6
7#include <cstdint>
8#include <cstdlib>
9#include <memory>
10#include <mutex>
11
12#if defined(GGML_USE_HIP)
13#define GGML_COMMON_DECL_HIP
14#define GGML_COMMON_IMPL_HIP
15#else
16#define GGML_COMMON_DECL_CUDA
17#define GGML_COMMON_IMPL_CUDA
18#if defined(GGML_USE_MUSA)
19#define GGML_COMMON_DECL_MUSA
20#define GGML_COMMON_IMPL_MUSA
21#endif
22#endif
23#include "ggml-common.h"
24
25#include <array>
26#include <algorithm>
27#include <cassert>
28#include <cfloat>
29#include <cstdio>
30#include <string>
31#include <unordered_map>
32#include <utility>
33#include <vector>
34
35#if defined(GGML_USE_HIP)
36#include "vendors/hip.h"
37#elif defined(GGML_USE_MUSA)
38#include "vendors/musa.h"
39#else
40#include "vendors/cuda.h"
41#endif // defined(GGML_USE_HIP)
42
43#define STRINGIZE_IMPL(...) #__VA_ARGS__
44#define STRINGIZE(...) STRINGIZE_IMPL(__VA_ARGS__)
45
46#define WARP_SIZE 32
47#define CUDART_HMAX   11070 // CUDA 11.7, min. ver. for which __hmax and __hmax2 are known to work (may be higher than needed)
48#define CUDART_HMASK  12000 // CUDA 12.0, min. ver. for half2 -> uint mask comparisons
49
50#define GGML_CUDA_CC_PASCAL          600
51#define GGML_CUDA_CC_DP4A            610 // minimum compute capability for __dp4a, an intrinsic for byte-wise dot products
52#define GGML_CUDA_CC_VOLTA           700
53#define GGML_CUDA_CC_TURING          750
54#define GGML_CUDA_CC_AMPERE          800
55#define GGML_CUDA_CC_ORIN            870
56#define GGML_CUDA_CC_ADA_LOVELACE    890
57#define GGML_CUDA_CC_HOPPER          900
58// While BW spans CC 1000, 1100 & 1200, we are integrating Tensor Core instructions available to 1200 family, see
59// https://docs.nvidia.com/cutlass/media/docs/cpp/blackwell_functionality.html#blackwell-sm120-gemms
60#define GGML_CUDA_CC_BLACKWELL       1200
61#define GGML_CUDA_CC_DGX_SPARK       1210
62#define GGML_CUDA_CC_RUBIN           1300
63#define GGML_CUDA_CC_OFFSET_AMD      0x1000000
64#define GGML_CUDA_CC_OFFSET_MTHREADS 0x0100000
65#define GGML_CUDA_CC_IS_NVIDIA(cc)   (cc < GGML_CUDA_CC_OFFSET_MTHREADS)
66
67// AMD
68// GCN/CDNA, wave size is 64
69#define GGML_CUDA_CC_GCN4       (GGML_CUDA_CC_OFFSET_AMD + 0x803)  // Tonga, Fiji, Polaris, minimum for fast fp16
70#define GGML_CUDA_CC_VEGA       (GGML_CUDA_CC_OFFSET_AMD + 0x900)  // Vega56/64, minimum for fp16 dual issue
71#define GGML_CUDA_CC_VEGA20     (GGML_CUDA_CC_OFFSET_AMD + 0x906)  // MI50/Radeon VII, minimum for dp4a
72#define GGML_CUDA_CC_GFX909     (GGML_CUDA_CC_OFFSET_AMD + 0x909)  // GCN APU
73#define GGML_CUDA_CC_GFX90C     (GGML_CUDA_CC_OFFSET_AMD + 0x90c)  // GCN APU
74#define GGML_CUDA_CC_CDNA1      (GGML_CUDA_CC_OFFSET_AMD + 0x908)  // MI100, minimum for MFMA, acc registers
75#define GGML_CUDA_CC_CDNA2      (GGML_CUDA_CC_OFFSET_AMD + 0x90a)  // MI210 (gfx90a), minimum acc register renaming
76#define GGML_CUDA_CC_CDNA3      (GGML_CUDA_CC_OFFSET_AMD + 0x942)  // MI300
77#define GGML_CUDA_CC_CDNA4      (GGML_CUDA_CC_OFFSET_AMD + 0x950)  // MI350X/MI355X
78
79// RDNA removes MFMA, dp4a, xnack, acc registers, wave size is 32
80#define GGML_CUDA_CC_RDNA1      (GGML_CUDA_CC_OFFSET_AMD + 0x1010) // RX 5000
81#define GGML_CUDA_CC_RDNA2      (GGML_CUDA_CC_OFFSET_AMD + 0x1030) // RX 6000, minimum for dp4a
82#define GGML_CUDA_CC_RDNA3      (GGML_CUDA_CC_OFFSET_AMD + 0x1100) // RX 7000, minimum for WMMA
83#define GGML_CUDA_CC_RDNA3_5    (GGML_CUDA_CC_OFFSET_AMD + 0x1150) // AI 370, AI Max 395 laptops.
84#define GGML_CUDA_CC_RDNA4      (GGML_CUDA_CC_OFFSET_AMD + 0x1200) // RX 9000
85
86#define GGML_CUDA_CC_IS_AMD(cc)     (cc >= GGML_CUDA_CC_OFFSET_AMD)
87#define GGML_CUDA_CC_IS_RDNA(cc)    (cc >= GGML_CUDA_CC_RDNA1)
88#define GGML_CUDA_CC_IS_RDNA1(cc)   (cc >= GGML_CUDA_CC_RDNA1 && cc < GGML_CUDA_CC_RDNA2)
89#define GGML_CUDA_CC_IS_RDNA2(cc)   (cc >= GGML_CUDA_CC_RDNA2 && cc < GGML_CUDA_CC_RDNA3)
90#define GGML_CUDA_CC_IS_RDNA3_0(cc) (cc >= GGML_CUDA_CC_RDNA3 && cc < GGML_CUDA_CC_RDNA3_5)
91#define GGML_CUDA_CC_IS_RDNA3_5(cc) (cc >= GGML_CUDA_CC_RDNA3_5 && cc < GGML_CUDA_CC_RDNA4)
92#define GGML_CUDA_CC_IS_RDNA3(cc)   (GGML_CUDA_CC_IS_RDNA3_0(cc) || GGML_CUDA_CC_IS_RDNA3_5(cc))
93#define GGML_CUDA_CC_IS_RDNA4(cc)   (cc >= GGML_CUDA_CC_RDNA4)
94#define GGML_CUDA_CC_IS_GCN_APU(cc) ((cc) == GGML_CUDA_CC_GFX909 || (cc) == GGML_CUDA_CC_GFX90C)
95#define GGML_CUDA_CC_IS_GCN(cc)     ((cc > GGML_CUDA_CC_OFFSET_AMD && cc < GGML_CUDA_CC_CDNA1) || GGML_CUDA_CC_IS_GCN_APU(cc))
96#define GGML_CUDA_CC_IS_CDNA(cc)    (!GGML_CUDA_CC_IS_GCN_APU(cc) && cc >= GGML_CUDA_CC_CDNA1 && cc < GGML_CUDA_CC_RDNA1)
97#define GGML_CUDA_CC_IS_CDNA1(cc)   (GGML_CUDA_CC_IS_CDNA(cc) && cc >= GGML_CUDA_CC_CDNA1 && cc < GGML_CUDA_CC_CDNA2)
98#define GGML_CUDA_CC_IS_CDNA2(cc)   (GGML_CUDA_CC_IS_CDNA(cc) && cc >= GGML_CUDA_CC_CDNA2 && cc < GGML_CUDA_CC_CDNA3)
99#define GGML_CUDA_CC_IS_CDNA3(cc)   (GGML_CUDA_CC_IS_CDNA(cc) && cc >= GGML_CUDA_CC_CDNA3 && cc < GGML_CUDA_CC_CDNA4)
100#define GGML_CUDA_CC_IS_CDNA4(cc)   (GGML_CUDA_CC_IS_CDNA(cc) && cc >= GGML_CUDA_CC_CDNA4 && cc < GGML_CUDA_CC_RDNA1)
101
102// Moore Threads
103#define MUSART_HMASK 40300 // MUSA rc4.3, min. ver. for half2 -> uint mask comparisons
104
105#define GGML_CUDA_CC_QY1 (GGML_CUDA_CC_OFFSET_MTHREADS + 0x210) // MTT S80, MTT S3000
106#define GGML_CUDA_CC_QY2 (GGML_CUDA_CC_OFFSET_MTHREADS + 0x220) // MTT S4000
107#define GGML_CUDA_CC_PH1 (GGML_CUDA_CC_OFFSET_MTHREADS + 0x310) // MTT S5000
108
109#define GGML_CUDA_CC_IS_MTHREADS(cc) (cc >= GGML_CUDA_CC_OFFSET_MTHREADS && cc < GGML_CUDA_CC_OFFSET_AMD)
110#define GGML_CUDA_CC_IS_QY1(cc)      (cc >= GGML_CUDA_CC_QY1 && cc < GGML_CUDA_CC_QY2)
111#define GGML_CUDA_CC_IS_QY2(cc)      (cc >= GGML_CUDA_CC_QY2 && cc < GGML_CUDA_CC_PH1)
112#define GGML_CUDA_CC_IS_PH1(cc)      (cc >= GGML_CUDA_CC_PH1)
113
114#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA) && CUDART_VERSION >= 11070
115#    define GGML_CUDA_USE_CUB
116#endif  // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA) && CUDART_VERSION >= 11070
117
118// PDL host-side support (cudaLaunchKernelEx) requires CUDART >= 11.8.
119// However, this has been bugged in CTK < 12.3 for MSVC builds, see
120// https://github.com/ggml-org/llama.cpp/pull/22522#discussion_r3302393293
121// __CUDA_ARCH__  is undefined in host passes; GPU arch check happens in device-side code.
122#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA) && \
123    (CUDART_VERSION >= 12030 || (!(defined(_MSC_VER) && !defined(__clang__)) && CUDART_VERSION >= 11080))
124#    define GGML_CUDA_USE_PDL
125#endif  // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA) && (CUDART_VERSION >= 12030 || (!(defined(_MSC_VER) && !defined(__clang__)) && CUDART_VERSION >= 11080))
126
127static __device__ __forceinline__ void ggml_cuda_syncwarp() {
128#ifndef GGML_USE_HIP
129    __syncwarp();
130#endif // GGML_USE_HIP
131}
132
133static __device__ __forceinline__ void ggml_cuda_pdl_sync() {
134#if defined(GGML_CUDA_USE_PDL) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_HOPPER
135    cudaGridDependencySynchronize();
136#endif // defined(GGML_CUDA_USE_PDL) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_HOPPER
137}
138
139static __device__ __forceinline__ void ggml_cuda_pdl_lc() {
140#if defined(GGML_CUDA_USE_PDL) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_HOPPER
141    cudaTriggerProgrammaticLaunchCompletion();
142#endif // defined(GGML_CUDA_USE_PDL) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_HOPPER
143}
144
145#ifdef __CUDA_ARCH_LIST__
146constexpr bool ggml_cuda_has_arch_impl(int) {
147    return false;
148}
149
150template<class ... Archs>
151constexpr bool ggml_cuda_has_arch_impl(const int arch, const int first, Archs... rest) {
152    return arch == first || ggml_cuda_has_arch_impl(arch, rest...);
153}
154
155constexpr bool ggml_cuda_has_arch(const int arch) {
156    return ggml_cuda_has_arch_impl(arch, __CUDA_ARCH_LIST__);
157}
158
159constexpr int ggml_cuda_highest_compiled_arch_impl(const int /*arch*/, const int cur) {
160    if (cur == 0) {
161        return -1;
162    }
163    return cur;
164}
165
166template<class ... Archs>
167constexpr int ggml_cuda_highest_compiled_arch_impl(const int arch, const int cur, const int first, Archs... rest) {
168    if (first <= arch && first > cur) {
169        return ggml_cuda_highest_compiled_arch_impl(arch, first, rest...);
170    } else {
171        return ggml_cuda_highest_compiled_arch_impl(arch, cur, rest...);
172    }
173}
174
175constexpr int ggml_cuda_highest_compiled_arch(const int arch) {
176    return ggml_cuda_highest_compiled_arch_impl(arch, 0, __CUDA_ARCH_LIST__);
177}
178#else
179static int ggml_cuda_highest_compiled_arch(const int arch) {
180    return arch;
181}
182#endif // __CUDA_ARCH_LIST__
183
184// ---------------------------------------------------------------------------------------------------------
185
186#define MATRIX_ROW_PADDING 512 // last row of quant. matrices is a multiple of this to avoid out-of-bounds memory accesses
187
188#define GGML_CUDA_MAX_STREAMS 8
189
190[[noreturn]]
191void ggml_cuda_error(const char * stmt, const char * func, const char * file, int line, const char * msg);
192
193#define CUDA_CHECK_GEN(err, success, error_fn)                                      \
194     do {                                                                           \
195        auto err_ = (err);                                                          \
196        if (err_ != (success)) {                                                    \
197            ggml_cuda_error(#err, __func__, __FILE__, __LINE__, error_fn(err_));    \
198        }                                                                           \
199    } while (0)
200
201#define CUDA_CHECK(err) CUDA_CHECK_GEN(err, cudaSuccess, cudaGetErrorString)
202
203
204#if CUDART_VERSION >= 12000 || defined(GGML_USE_MUSA)
205    static const char * cublas_get_error_str(const cublasStatus_t err) {
206        return cublasGetStatusString(err);
207    }
208#else
209    static const char * cublas_get_error_str(const cublasStatus_t err) {
210        switch (err) {
211            case CUBLAS_STATUS_SUCCESS: return "CUBLAS_STATUS_SUCCESS";
212            case CUBLAS_STATUS_NOT_INITIALIZED: return "CUBLAS_STATUS_NOT_INITIALIZED";
213            case CUBLAS_STATUS_ALLOC_FAILED: return "CUBLAS_STATUS_ALLOC_FAILED";
214            case CUBLAS_STATUS_INVALID_VALUE: return "CUBLAS_STATUS_INVALID_VALUE";
215            case CUBLAS_STATUS_ARCH_MISMATCH: return "CUBLAS_STATUS_ARCH_MISMATCH";
216            case CUBLAS_STATUS_MAPPING_ERROR: return "CUBLAS_STATUS_MAPPING_ERROR";
217            case CUBLAS_STATUS_EXECUTION_FAILED: return "CUBLAS_STATUS_EXECUTION_FAILED";
218            case CUBLAS_STATUS_INTERNAL_ERROR: return "CUBLAS_STATUS_INTERNAL_ERROR";
219            case CUBLAS_STATUS_NOT_SUPPORTED: return "CUBLAS_STATUS_NOT_SUPPORTED";
220            default: return "unknown error";
221        }
222    }
223#endif // CUDART_VERSION >= 12000
224
225#define CUBLAS_CHECK(err) CUDA_CHECK_GEN(err, CUBLAS_STATUS_SUCCESS, cublas_get_error_str)
226
227#ifdef GGML_USE_NCCL
228#define NCCL_CHECK(err) CUDA_CHECK_GEN(err, ncclSuccess, ncclGetErrorString)
229#endif // GGML_USE_NCCL
230
231#if !defined(GGML_USE_HIP) && !defined(GGML_CUDA_NO_VMM)
232static const char * cu_get_error_str(CUresult err) {
233    const char * err_str;
234    cuGetErrorString(err, &err_str);
235    return err_str;
236}
237#define CU_CHECK(err) CUDA_CHECK_GEN(err, CUDA_SUCCESS, cu_get_error_str)
238#endif
239
240#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
241#    define CUDA_SET_SHARED_MEMORY_LIMIT(kernel, nbytes)                                                       \
242        do {                                                                                                   \
243            static bool shared_memory_limit_raised[GGML_CUDA_MAX_DEVICES] = { false };                         \
244            const int   id                                                = ggml_cuda_get_device();            \
245            if (!shared_memory_limit_raised[id]) {                                                             \
246                CUDA_CHECK(cudaFuncSetAttribute(kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, nbytes)); \
247                shared_memory_limit_raised[id] = true;                                                         \
248            }                                                                                                  \
249        } while (0)
250#else
251#    define CUDA_SET_SHARED_MEMORY_LIMIT(kernel, nbytes) \
252        do {                                             \
253            GGML_UNUSED(nbytes);                         \
254        } while (0)
255#endif // !(defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
256
257#if CUDART_VERSION >= 11010 || defined(GGML_USE_MUSA)
258#define GGML_CUDA_ASSUME(x) __builtin_assume(x)
259#else
260#define GGML_CUDA_ASSUME(x)
261#endif // CUDART_VERSION >= 11010
262
263#if (!defined(GGML_USE_HIP) && !defined(GGML_CUDA_NO_VMM)) || (defined(GGML_USE_HIP) && !defined(GGML_HIP_NO_VMM))
264#define GGML_USE_VMM
265#endif // (!defined(GGML_USE_HIP) && !defined(GGML_CUDA_NO_VMM)) || (defined(GGML_USE_HIP) && !defined(GGML_HIP_NO_VMM))
266
267#if defined(GGML_USE_HIP) || defined(GGML_USE_MUSA) || __CUDA_ARCH__ >= GGML_CUDA_CC_PASCAL
268#define FP16_AVAILABLE
269#endif // defined(GGML_USE_HIP) || defined(GGML_USE_MUSA) || __CUDA_ARCH__ >= GGML_CUDA_CC_PASCAL
270
271#if defined(FP16_AVAILABLE) && __CUDA_ARCH__ != 610
272#define FAST_FP16_AVAILABLE
273#endif // defined(FP16_AVAILABLE) && __CUDA_ARCH__ != 610
274
275#if defined(GGML_USE_HIP) && defined(CDNA) && !defined(GGML_HIP_NO_MMQ_MFMA)
276#define AMD_MFMA_AVAILABLE
277#endif // defined(GGML_USE_HIP) && defined(CDNA) && !defined(GGML_HIP_NO_MMQ_MFMA)
278
279#if defined(GGML_USE_HIP) && (defined(RDNA4) || defined(RDNA3))
280#define AMD_WMMA_AVAILABLE
281#endif // defined(GGML_USE_HIP) && defined(RDNA4)
282
283// The Volta instructions are in principle available on Turing or newer but they are effectively unusable:
284#if !defined(GGML_USE_HIP) && __CUDA_ARCH__ == GGML_CUDA_CC_VOLTA
285#define VOLTA_MMA_AVAILABLE
286#endif // !defined(GGML_USE_HIP) && __CUDA_ARCH__ == GGML_CUDA_CC_VOLTA
287
288#if !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_TURING
289#define TURING_MMA_AVAILABLE
290#endif // !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_TURING
291
292#if !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
293#define AMPERE_MMA_AVAILABLE
294#endif // !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
295
296#if !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_BLACKWELL && __CUDA_ARCH__ < GGML_CUDA_CC_RUBIN
297#    define BLACKWELL_MMA_AVAILABLE
298#endif // !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_BLACKWELL
299
300#if !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
301#define CP_ASYNC_AVAILABLE
302#endif // !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
303
304#if !defined(GGML_CUDA_NO_FA) && !(defined(GGML_USE_MUSA) && __MUSA_ARCH__ < 220)
305#define FLASH_ATTN_AVAILABLE
306#endif // !defined(GGML_CUDA_NO_FA) && !(defined(GGML_USE_MUSA) && __MUSA_ARCH__ < 220)
307
308static bool fp16_available(const int cc) {
309    return ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_PASCAL ||
310        (GGML_CUDA_CC_IS_MTHREADS(cc) && cc >= GGML_CUDA_CC_PH1);
311}
312
313static bool fast_fp16_available(const int cc) {
314    return GGML_CUDA_CC_IS_AMD(cc) ||
315        (GGML_CUDA_CC_IS_NVIDIA(cc) && fp16_available(cc) && ggml_cuda_highest_compiled_arch(cc) != 610) ||
316        (GGML_CUDA_CC_IS_MTHREADS(cc) && fp16_available(cc));
317}
318
319// To be used for feature selection of external libraries, e.g. cuBLAS.
320static bool fast_fp16_hardware_available(const int cc) {
321    return (GGML_CUDA_CC_IS_NVIDIA(cc) && cc >= GGML_CUDA_CC_PASCAL && cc != 610) || GGML_CUDA_CC_IS_AMD(cc) ||
322        (GGML_CUDA_CC_IS_MTHREADS(cc) && cc >= GGML_CUDA_CC_QY2);
323}
324
325// To be used for feature selection of external libraries, e.g. cuBLAS.
326static bool fp16_mma_hardware_available(const int cc) {
327    return (GGML_CUDA_CC_IS_NVIDIA(cc) && cc >= GGML_CUDA_CC_VOLTA) ||
328        GGML_CUDA_CC_IS_CDNA(cc) || GGML_CUDA_CC_IS_RDNA3(cc) || GGML_CUDA_CC_IS_RDNA4(cc) ||
329        (GGML_CUDA_CC_IS_MTHREADS(cc) && cc >= GGML_CUDA_CC_QY2);
330}
331
332// To be used for feature selection of external libraries, e.g. cuBLAS.
333static bool fast_bf16_hardware_available(const int cc) {
334        return (GGML_CUDA_CC_IS_AMD(cc) && (cc >= GGML_CUDA_CC_RDNA3 || GGML_CUDA_CC_IS_CDNA(cc)))
335            || (GGML_CUDA_CC_IS_NVIDIA(cc) && cc >= GGML_CUDA_CC_AMPERE);
336}
337
338static bool bf16_mma_hardware_available(const int cc) {
339    return (GGML_CUDA_CC_IS_NVIDIA(cc) && cc >= GGML_CUDA_CC_AMPERE) ||
340        GGML_CUDA_CC_IS_CDNA(cc) || cc >= GGML_CUDA_CC_RDNA3 ||
341        (GGML_CUDA_CC_IS_MTHREADS(cc) && cc >= GGML_CUDA_CC_PH1);
342}
343
344static bool fp32_mma_hardware_available(const int cc) {
345    return GGML_CUDA_CC_IS_CDNA(cc);
346}
347
348static bool amd_mfma_available(const int cc) {
349#if !defined(GGML_HIP_NO_MMQ_MFMA)
350    return GGML_CUDA_CC_IS_CDNA(cc);
351#else
352    return false;
353#endif //!defined(GGML_HIP_NO_MMQ_MFMA)
354}
355
356static bool amd_wmma_available(const int cc) {
357    return (GGML_CUDA_CC_IS_RDNA4(cc) || GGML_CUDA_CC_IS_RDNA3(cc));
358}
359
360static bool volta_mma_available(const int cc) {
361    return GGML_CUDA_CC_IS_NVIDIA(cc) && ggml_cuda_highest_compiled_arch(cc) == GGML_CUDA_CC_VOLTA;
362}
363
364static bool turing_mma_available(const int cc) {
365    return GGML_CUDA_CC_IS_NVIDIA(cc) && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_TURING;
366}
367
368static bool ampere_mma_available(const int cc) {
369    return GGML_CUDA_CC_IS_NVIDIA(cc) && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_AMPERE;
370}
371
372static bool cp_async_available(const int cc) {
373    return GGML_CUDA_CC_IS_NVIDIA(cc) && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_AMPERE;
374}
375
376static bool blackwell_mma_available(const int cc) {
377    return GGML_CUDA_CC_IS_NVIDIA(cc) && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_BLACKWELL &&
378           ggml_cuda_highest_compiled_arch(cc) < GGML_CUDA_CC_RUBIN;
379}
380
381// Checks whether the tensor's base data pointer and higher-dimensional strides are byte-aligned to `alignment` bytes.
382static bool ggml_cuda_is_aligned(const ggml_tensor * tensor, const size_t alignment) {
383    GGML_ASSERT(tensor != nullptr);
384    return (reinterpret_cast<uintptr_t>(tensor->data) % alignment) == 0 &&
385           tensor->nb[1] % alignment == 0 &&
386           tensor->nb[2] % alignment == 0 &&
387           tensor->nb[3] % alignment == 0;
388}
389
390static constexpr __device__ int ggml_cuda_get_physical_warp_size() {
391#if defined(GGML_USE_HIP) && (defined(__GFX9__) || defined(__GFX8__))
392    return 64;
393#else
394    return 32;
395#endif // defined(GGML_USE_HIP) && (defined(__GFX9__) || defined(__GFX8__))
396}
397
398// Maximum number of bytes that can be copied in a single instruction.
399static constexpr __device__ int ggml_cuda_get_max_cpy_bytes() {
400#ifdef GGML_USE_HIP
401    return 16;
402#else
403#if __CUDA_ARCH__ >= GGML_CUDA_CC_VOLTA
404    return 16;
405#else
406    return 8;
407#endif // __CUDA_ARCH__ >= GGML_CUDA_CC_VOLTA
408#endif // GGML_USE_HIP
409}
410
411
412[[noreturn]]
413static __device__ void no_device_code(
414    const char * file_name, const int line, const char * function_name, const int arch, const char * arch_list) {
415
416#if defined(GGML_USE_HIP)
417    printf("%s:%d: ERROR: HIP kernel %s has no device code compatible with HIP arch %d.\n",
418           file_name, line, function_name, arch);
419    GGML_UNUSED(arch_list);
420#else
421    printf("%s:%d: ERROR: CUDA kernel %s has no device code compatible with CUDA arch %d. ggml-cuda.cu was compiled for: %s\n",
422           file_name, line, function_name, arch, arch_list);
423#endif // defined(GGML_USE_HIP)
424    __trap();
425
426    GGML_UNUSED(no_device_code); // suppress unused function warning
427
428#if defined(GGML_USE_MUSA)
429    __builtin_unreachable();
430#endif // defined(GGML_USE_MUSA)
431}
432
433#ifdef __CUDA_ARCH__
434#define NO_DEVICE_CODE no_device_code(__FILE__, __LINE__, __FUNCTION__, __CUDA_ARCH__, STRINGIZE(__CUDA_ARCH_LIST__))
435#else
436#define NO_DEVICE_CODE //GGML_ABORT("NO_DEVICE_CODE not valid in host code.")
437#endif // __CUDA_ARCH__
438
439// The compiler is always able to unroll loops if they contain continue expressions.
440// In such cases loop unrolling can still be achieved via recursion:
441template <int n>
442struct ggml_cuda_unroll {
443    template <typename Func, typename... Args>
444    __device__ void operator()(const Func & f, Args... args) const {
445        f(n - 1, args...);
446        ggml_cuda_unroll<n - 1>{}(f, args...);
447    }
448};
449
450template <>
451struct ggml_cuda_unroll<1> {
452    template <typename Func, typename... Args>
453    __device__ void operator()(const Func & f, Args... args) const {
454        f(0, args...);
455    }
456};
457
458template<int width = WARP_SIZE>
459static __device__ __forceinline__ int warp_reduce_sum(int x) {
460#if !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
461    return __reduce_add_sync(0xffffffff, x);
462#else
463#pragma unroll
464    for (int offset = width/2; offset > 0; offset >>= 1) {
465        x += __shfl_xor_sync(0xffffffff, x, offset, width);
466    }
467    return x;
468#endif // !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
469}
470
471template<int width = WARP_SIZE>
472static __device__ __forceinline__ float warp_reduce_sum(float x) {
473#pragma unroll
474    for (int offset = width/2; offset > 0; offset >>= 1) {
475        x += __shfl_xor_sync(0xffffffff, x, offset, width);
476    }
477    return x;
478}
479
480template<int width = WARP_SIZE>
481static __device__ __forceinline__ float2 warp_reduce_sum(float2 a) {
482#pragma unroll
483    for (int offset = width/2; offset > 0; offset >>= 1) {
484        a.x += __shfl_xor_sync(0xffffffff, a.x, offset, width);
485        a.y += __shfl_xor_sync(0xffffffff, a.y, offset, width);
486    }
487    return a;
488}
489
490template<int width = WARP_SIZE>
491static __device__ __forceinline__ half2 warp_reduce_sum(half2 a) {
492#ifdef FP16_AVAILABLE
493#pragma unroll
494    for (int offset = width/2; offset > 0; offset >>= 1) {
495        a = __hadd2(a, __shfl_xor_sync(0xffffffff, a, offset, width));
496    }
497    return a;
498
499#else
500    NO_DEVICE_CODE;
501    return a;
502#endif // FP16_AVAILABLE
503}
504
505template<int width = WARP_SIZE>
506static __device__ __forceinline__ int warp_reduce_all(int x) {
507    if (width == ggml_cuda_get_physical_warp_size()) {
508        return __all_sync(0xffffffff, x);
509    } else {
510#pragma unroll
511        for (int offset = width/2; offset > 0; offset >>= 1) {
512            x = __shfl_xor_sync(0xffffffff, x, offset, width) && x;
513        }
514        return x;
515    }
516}
517
518template<int width = WARP_SIZE>
519static __device__ __forceinline__ int warp_reduce_any(int x) {
520    if (width == ggml_cuda_get_physical_warp_size()) {
521        return __any_sync(0xffffffff, x);
522    } else {
523#pragma unroll
524        for (int offset = width/2; offset > 0; offset >>= 1) {
525            x = __shfl_xor_sync(0xffffffff, x, offset, width) || x;
526        }
527        return x;
528    }
529}
530
531template<int width = WARP_SIZE>
532static __device__ __forceinline__ float warp_reduce_max(float x) {
533#pragma unroll
534    for (int offset = width/2; offset > 0; offset >>= 1) {
535        x = fmaxf(x, __shfl_xor_sync(0xffffffff, x, offset, width));
536    }
537    return x;
538}
539
540template<typename T, int width = WARP_SIZE>
541static __device__ __forceinline__ T warp_prefix_inclusive_sum(T x) {
542    const int lane_id = threadIdx.x % width;
543#pragma unroll
544    for (int offset = 1; offset < width; offset <<= 1) {
545        const T t = __shfl_up_sync(0xffffffff, x, offset, width);
546        if (lane_id >= offset) {
547            x += t;
548        }
549    }
550    return x;
551}
552
553template<int width = WARP_SIZE>
554static __device__ __forceinline__ float2 warp_prefix_inclusive_sum(float2 a) {
555    const int lane_id = threadIdx.x % width;
556#pragma unroll
557    for (int offset = 1; offset < width; offset <<= 1) {
558        const float t_x = __shfl_up_sync(0xffffffff, a.x, offset, width);
559        const float t_y = __shfl_up_sync(0xffffffff, a.y, offset, width);
560        if (lane_id >= offset) {
561            a.x += t_x;
562            a.y += t_y;
563        }
564    }
565    return a;
566}
567
568template<int width = WARP_SIZE>
569static __device__ __forceinline__ half2 warp_prefix_inclusive_sum(half2 a) {
570#ifdef FP16_AVAILABLE
571    const int lane_id = threadIdx.x % width;
572#pragma unroll
573    for (int offset = 1; offset < width; offset <<= 1) {
574        const half2 t = __shfl_up_sync(0xffffffff, a, offset, width);
575        if (lane_id >= offset) {
576            a = __hadd2(a, t);
577        }
578    }
579    return a;
580
581#else
582    NO_DEVICE_CODE;
583    return a;
584#endif // FP16_AVAILABLE
585}
586
587enum class block_reduce_method {
588    MAX,
589    SUM,
590};
591
592template<block_reduce_method method_t, typename T>
593struct block_reduce_policy;
594
595template <typename T, typename... Ts>
596inline constexpr bool is_any = (std::is_same_v<T, Ts> || ...);
597
598template<typename...>
599inline constexpr bool ggml_cuda_dependent_false_v = false;
600
601template <typename T> struct block_reduce_policy<block_reduce_method::SUM, T> {
602    static __device__ T reduce(T val) {
603        if constexpr(is_any<T, float, float2, half2, int>) {
604            return warp_reduce_sum(val);
605        } else {
606            static_assert(ggml_cuda_dependent_false_v<T>, "Unsupported type for block reduce sum");
607        }
608    }
609
610    static __device__ T sentinel() {
611        if constexpr (std::is_same_v<T, float>) {
612            return 0.0f;
613        } else if constexpr (std::is_same_v<T, float2>) {
614            return make_float2(0.0f, 0.0f);
615        } else if constexpr (std::is_same_v<T, half2>) {
616            return make_half2(0.0f, 0.0f);
617        } else if constexpr (std::is_same_v<T, int>) {
618            return 0;
619        } else {
620            static_assert(ggml_cuda_dependent_false_v<T>, "Unsupported type for block reduce sum");
621        }
622    }
623};
624
625template <typename T> struct block_reduce_policy<block_reduce_method::MAX, T> {
626    static __device__ T reduce(T val) {
627        if constexpr (is_any<T, float, half2>) {
628            return warp_reduce_max(val);
629        } else {
630            static_assert(ggml_cuda_dependent_false_v<T>, "Unsupported type for block reduce max");
631        }
632    }
633
634    static __device__ T sentinel() {
635        if constexpr (std::is_same_v<T, float>) {
636            return -INFINITY;
637        } else if constexpr (std::is_same_v<T, half2>) {
638            return make_half2(-INFINITY, -INFINITY);
639        } else {
640            static_assert(ggml_cuda_dependent_false_v<T>, "Unsupported type for block reduce max");
641        }
642    }
643};
644
645template <block_reduce_method reduce_method_t, const unsigned int block_size_template = 0, typename T>
646static __device__ T block_reduce(T val, [[maybe_unused]] T * shared_vals) {
647    // for multi-warp reductions, callers must not reuse shared_vals until all reads from this invocation have completed
648    val                           = block_reduce_policy<reduce_method_t, T>::reduce(val);
649    const unsigned int block_size = block_size_template == 0 ? blockDim.x : block_size_template;
650    if (block_size > WARP_SIZE) {
651        assert((block_size <= 1024) && (block_size % WARP_SIZE) == 0);
652        const int warp_id = threadIdx.x / WARP_SIZE;
653        const int lane_id = threadIdx.x % WARP_SIZE;
654        if (lane_id == 0) {
655            shared_vals[warp_id] = val;
656        }
657        __syncthreads();
658        val = block_reduce_policy<reduce_method_t, T>::sentinel();
659        if (lane_id < (static_cast<int>(block_size) / WARP_SIZE)) {
660            val = shared_vals[lane_id];
661        }
662        return block_reduce_policy<reduce_method_t, T>::reduce(val);
663    }
664
665    return val;
666}
667
668static __device__ __forceinline__ half ggml_cuda_hmax(const half a, const half b) {
669#ifdef FP16_AVAILABLE
670
671#if !defined(GGML_USE_HIP) && CUDART_VERSION < CUDART_HMAX
672    return __float2half(fmaxf(__half2float(a), __half2float(b)));
673#else
674    return __hmax(a, b);
675#endif // !defined(GGML_USE_HIP) && CUDART_VERSION < CUDART_HMAX
676
677#else
678   NO_DEVICE_CODE;
679   GGML_UNUSED(b);
680   return a;
681#endif // FP16_AVAILABLE
682}
683
684static __device__ __forceinline__ half2 ggml_cuda_hmax2(const half2 a, const half2 b) {
685#if defined(GGML_USE_HIP)
686    return half2(__hmax(a.x, b.x), __hmax(a.y, b.y));
687#elif CUDART_VERSION >= CUDART_HMAX
688    return __hmax2(a, b);
689#else
690    half2 ret;
691    reinterpret_cast<half&>(ret.x) = __float2half(fmaxf( __low2float(a),  __low2float(b)));
692    reinterpret_cast<half&>(ret.y) = __float2half(fmaxf(__high2float(a), __high2float(b)));
693    return ret;
694#endif
695}
696
697template<int width = WARP_SIZE>
698static __device__ __forceinline__ half2 warp_reduce_max(half2 x) {
699#if !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_PASCAL || defined(GGML_USE_HIP)
700#pragma unroll
701   for (int offset = width/2; offset > 0; offset >>= 1) {
702       x = ggml_cuda_hmax2(x, __shfl_xor_sync(0xffffffff, x, offset, width));
703   }
704   return x;
705#else
706   GGML_UNUSED(x);
707   NO_DEVICE_CODE;
708#endif // !defined(GGML_USE_HIP) && __CUDA_ARCH__ >= GGML_CUDA_CC_PASCAL || defined(GGML_USE_HIP)
709}
710
711#if (defined(CUDART_VERSION) && CUDART_VERSION < CUDART_HMASK) || defined(GGML_USE_HIP) || \
712    (defined(MUSART_VERSION) && MUSART_VERSION < MUSART_HMASK)
713static __device__ __forceinline__ uint32_t __hgt2_mask(const half2 a, const half2 b) {
714    const uint32_t mask_low  = 0x0000FFFF * (float( __low2half(a)) > float( __low2half(b)));
715    const uint32_t mask_high = 0xFFFF0000 * (float(__high2half(a)) > float(__high2half(b)));
716    return mask_low | mask_high;
717}
718#endif // (defined(CUDART_VERSION) && CUDART_VERSION < CUDART_HMASK) || defined(GGML_USE_HIP) || (defined(MUSART_VERSION) && MUSART_VERSION < MUSART_HMASK)
719
720static __device__ __forceinline__ int ggml_cuda_dp4a(const int a, const int b, int c) {
721#if defined(GGML_USE_HIP)
722#if defined(CDNA) || defined(RDNA2) || defined(__gfx906__)
723    c = __builtin_amdgcn_sdot4(a, b, c, false);
724#elif defined(RDNA3) || defined(RDNA4)
725    c = __builtin_amdgcn_sudot4( true, a, true, b, c, false);
726#elif defined(RDNA1) || defined(__gfx900__)
727    int tmp1;
728    int tmp2;
729    asm("\n \
730        v_mul_i32_i24 %1, sext(%3), sext(%4) dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:BYTE_0 \n \
731        v_mul_i32_i24 %2, sext(%3), sext(%4) dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:BYTE_1 \n \
732        v_add3_u32 %0, %1, %2, %0 \n \
733        v_mul_i32_i24 %1, sext(%3), sext(%4) dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_2 src1_sel:BYTE_2 \n \
734        v_mul_i32_i24 %2, sext(%3), sext(%4) dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:BYTE_3 \n \
735        v_add3_u32 %0, %1, %2, %0 \n \
736        "
737        : "+v"(c), "=&v"(tmp1), "=&v"(tmp2)
738        : "v"(a), "v"(b)
739    );
740#else
741    const int8x4_t va = reinterpret_cast<const int8x4_t&>(a);
742    const int8x4_t vb = reinterpret_cast<const int8x4_t&>(b);
743    c += va[0] * vb[0] + va[1] * vb[1] + va[2] * vb[2] + va[3] * vb[3];
744#endif
745    return c;
746
747#else // defined(GGML_USE_HIP)
748
749#if __CUDA_ARCH__ >= GGML_CUDA_CC_DP4A || defined(GGML_USE_MUSA)
750    return __dp4a(a, b, c);
751#else // __CUDA_ARCH__ >= GGML_CUDA_CC_DP4A || defined(GGML_USE_MUSA)
752    const int8_t * a8 = (const int8_t *) &a;
753    const int8_t * b8 = (const int8_t *) &b;
754    return c + a8[0]*b8[0] + a8[1]*b8[1] + a8[2]*b8[2] + a8[3]*b8[3];
755#endif // __CUDA_ARCH__ >= GGML_CUDA_CC_DP4A || defined(GGML_USE_MUSA)
756
757#endif // defined(GGML_USE_HIP)
758}
759
760static __device__ __forceinline__ void ggml_cuda_mad(float & acc, const float v, const float u) {
761    acc += v*u;
762}
763
764static __device__ __forceinline__ void ggml_cuda_mad(float & acc, const float2 v, const float2 u) {
765    acc += v.x*u.x;
766    acc += v.y*u.y;
767}
768
769#if defined(GGML_USE_HIP) && (defined(RDNA2) || defined(RDNA3) || defined(RDNA4) || defined(__gfx906__) || defined(CDNA))
770#define V_DOT2_F32_F16_AVAILABLE
771#endif // defined(GGML_USE_HIP) && (defined(RDNA2) || defined(RDNA3) || defined(RDNA4) || defined(__gfx906__) || defined(CDNA))
772
773static __device__ __forceinline__ void ggml_cuda_mad(float & acc, const half2 v, const half2 u) {
774#ifdef V_DOT2_F32_F16_AVAILABLE
775    asm volatile("v_dot2_f32_f16 %0, %1, %2, %0" : "+v"(acc) : "v"(v), "v"(u));
776#else
777#ifdef FAST_FP16_AVAILABLE
778    const float2 tmp = __half22float2(v*u);
779    acc += tmp.x + tmp.y;
780#else
781    const float2 tmpv = __half22float2(v);
782    const float2 tmpu = __half22float2(u);
783    acc += tmpv.x * tmpu.x;
784    acc += tmpv.y * tmpu.y;
785#endif // FAST_FP16_AVAILABLE
786#endif // V_DOT2_F32_F16_AVAILABLE
787}
788
789static __device__ __forceinline__ void ggml_cuda_mad(half2 & acc, const half2 v, const half2 u) {
790#ifdef FAST_FP16_AVAILABLE
791    acc += v*u;
792#else
793    const float2 tmpv = __half22float2(v);
794    const float2 tmpu = __half22float2(u);
795    float2 tmpacc = __half22float2(acc);
796    tmpacc.x += tmpv.x * tmpu.x;
797    tmpacc.y += tmpv.y * tmpu.y;
798    acc = make_half2(tmpacc.x, tmpacc.y);
799#endif // FAST_FP16_AVAILABLE
800}
801
802// Aligned memory transfers of 8/16 bytes can be faster than 2 transfers with 4 bytes, especially on AMD.
803// Important: do not use this function if dst and src both point at registers.
804//     Due to the strict aliasing rule the compiler can do incorrect optimizations if src and dst have different types.
805//     The function is intended for copies between registers and SRAM/VRAM to make the compiler emit the right instructions.
806//     If dst and src point at different address spaces then they are guaranteed to not be aliased.
807template <int nbytes, int alignment = 0>
808static __device__ __forceinline__ void ggml_cuda_memcpy_1(void * __restrict__ dst, const void * __restrict__ src) {
809    static_assert(
810        nbytes <= ggml_cuda_get_max_cpy_bytes() || alignment == 0,
811        "You are misusing the alignment parameter for ggml_cuda_memcpy_1. "
812        "The intent is for the parameter is only as a workaround if either one of the pointers is not properly aligned. "
813        "If you use it to do more bytes per copy than ggml_cuda_max_cpy_bytes() the reads and writes may not be coalesced. "
814        "Call ggml_cuda_memcpy_1 in a loop instead.");
815    if constexpr (alignment != 0) {
816        static_assert(nbytes % alignment == 0, "bad alignment");
817    }
818    constexpr int nb_per_cpy = alignment == 0 ? nbytes : alignment;
819
820#pragma unroll
821    for (int i = 0; i < nbytes/nb_per_cpy; ++i) {
822        if constexpr (nb_per_cpy == 1) {
823            ((char *) dst)[i] = ((const char *) src)[i];
824        } else if constexpr (nb_per_cpy == 2) {
825            ((short *) dst)[i] = ((const short *) src)[i];
826        } else if constexpr (nb_per_cpy == 4) {
827            ((int *) dst)[i] = ((const int *) src)[i];
828        } else if constexpr (nb_per_cpy == 8) {
829            ((int2 *) dst)[i] = ((const int2 *) src)[i];
830        } else if constexpr (nb_per_cpy == 16) {
831            ((int4 *) dst)[i] = ((const int4 *) src)[i];
832        } else {
833            static_assert(nbytes == 0 && nbytes == -1, "bad nbytes");
834        }
835    }
836}
837
838static __device__ __forceinline__ float ggml_cuda_e8m0_to_fp32(uint8_t x) {
839#if CUDART_VERSION >= 12080
840    const nv_bfloat16 e = __nv_cvt_e8m0_to_bf16raw(x);
841    return (float) e;
842#else
843    uint32_t bits;
844    if (x == 0) {
845        bits = 0x00400000;
846    } else {
847        bits = (uint32_t) x << 23;
848    }
849
850    float result;
851    memcpy(&result, &bits, sizeof(float));
852    return result;
853#endif // CUDART_VERSION >= 12050
854}
855
856static __device__ __forceinline__ float ggml_cuda_ue4m3_to_fp32(uint8_t x) {
857#if defined(GGML_USE_HIP) && defined(CDNA3) && defined(FP8_AVAILABLE) && HIP_VERSION >= 60200000
858    // ROCm does not support fp8 in software on devices with fp8 hardware,
859    // but CDNA3 supports only e4m3_fnuz (no inf).
860    const uint32_t bits = x * (x != 0x7F && x != 0xFF); // Convert NaN to 0.0f to match CPU implementation.
861    const __hip_fp8_e4m3_fnuz xf = *reinterpret_cast<const __hip_fp8_e4m3_fnuz *>(&bits);
862    return static_cast<float>(xf) / 2;
863#else
864#if defined(FP8_AVAILABLE) && !defined(GGML_USE_HIP)
865    const uint32_t bits = x * (x != 0x7F && x != 0xFF); // Convert NaN to 0.0f to match CPU implementation.
866    const __nv_fp8_e4m3 xf = *reinterpret_cast<const __nv_fp8_e4m3 *>(&bits);
867    return static_cast<float>(xf) / 2;
868#else
869    if (x == 0 || (x == 0x7F && x != 0xFF)) { // Convert NaN to 0.0f
870        return 0.0f;
871    }
872    const int exp = (x >> 3) & 0xF;
873    const int man = x & 0x7;
874    float raw;
875    if (exp == 0) {
876        raw = ldexpf((float) man, -9);
877    } else {
878        raw = ldexpf(1.0f + (float) man / 8.0f, exp - 7);
879    }
880    return static_cast<float>(raw / 2);
881#endif // defined(FP8_AVAILABLE) && !defined(GGML_USE_HIP)
882#endif // defined(GGML_USE_HIP) && defined(CDNA3) && defined(FP8_AVAILABLE) && HIP_VERSION >= 60200000
883}
884
885static __device__ __forceinline__ uint8_t ggml_cuda_fp32_to_ue4m3(float x) {
886#if defined(BLACKWELL_MMA_AVAILABLE) // This is used for NVFP4 subblock scale quantizations only
887    if (!(x > 0.0f)) {
888        return 0;
889    }
890    const __nv_fp8_e4m3 xf(x);
891    return xf.__x;
892#else
893     NO_DEVICE_CODE; // Used only for NVFP4 Scales for Activations, only for Blackwell
894#endif // defined(BLACKWELL_MMA_AVAILABLE)
895}
896
897__device__ __forceinline__ uint8_t ggml_cuda_float_to_fp4_e2m1(float x, float e) {
898    const uint8_t sign_bit = (x < 0.0f) << 3;
899    float         ax       = fabsf(x) * e;
900
901    // Positive LUT
902    static constexpr float pos_lut[8] = { 0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 6.0f };
903
904    int   best_i   = 0;
905    float best_err = fabsf(ax - pos_lut[0]);
906
907#pragma unroll
908    for (int i = 1; i < 8; ++i) {
909        const float err = fabsf(ax - pos_lut[i]);
910        if (err < best_err) {
911            best_err = err;
912            best_i   = i;
913        }
914    }
915
916    return static_cast<uint8_t>(best_i | sign_bit);
917}
918
919// See https://gmplib.org/~tege/divcnst-pldi94.pdf figure 4.1.
920// Precompute mp (m' in the paper) and L such that division
921// can be computed using a multiply (high 32b of 64b result)
922// and a shift:
923//
924// n/d = (mulhi(n, mp) + n) >> L;
925static const uint3 init_fastdiv_values(uint64_t d_64) {
926    GGML_ASSERT(d_64 != 0);
927    GGML_ASSERT(d_64 <= std::numeric_limits<uint32_t>::max());
928
929    uint32_t d = (uint32_t)d_64;
930
931    // compute L = ceil(log2(d));
932    uint32_t L = 0;
933    while (L < 32 && (uint32_t{ 1 } << L) < d) {
934        L++;
935    }
936
937    uint32_t mp = (uint32_t) ((uint64_t{ 1 } << 32) * ((uint64_t{ 1 } << L) - d) / d + 1);
938    // pack divisor as well to reduce error surface
939    return make_uint3(mp, L, d);
940}
941
942static __device__ __forceinline__ uint32_t fastdiv(uint32_t n, const uint3 fastdiv_values) {
943    // expects fastdiv_values to contain <mp, L, divisor> in <x, y, z>
944    // fastdiv_values.z is unused and optimized away by the compiler.
945    // Compute high 32 bits of n * mp
946    const uint32_t hi = __umulhi(n, fastdiv_values.x);
947    // add n, apply bit shift
948    return (hi + n) >> fastdiv_values.y;
949}
950
951static __device__ __forceinline__ uint32_t fastmodulo(uint32_t n, const uint3 fastdiv_values) {
952    // expects  fastdiv_values to contain <mp, L, divisor> in <x, y, z> (see init_fastdiv_values)
953    return n - fastdiv(n, fastdiv_values) * fastdiv_values.z;
954}
955
956// Calculate both division and modulo at once, returns <n/divisor, n%divisor>
957static __device__ __forceinline__ uint2 fast_div_modulo(uint32_t n, const uint3 fastdiv_values) {
958    // expects  fastdiv_values to contain <mp, L, divisor> in <x, y, z> (see init_fastdiv_values)
959    const uint32_t div_val = fastdiv(n, fastdiv_values);
960    const uint32_t mod_val = n - div_val * fastdiv_values.z;
961    return make_uint2(div_val, mod_val);
962}
963
964typedef void (*dequantize_kernel_t)(const void * vx, const int64_t ib, const int iqs, float2 & v);
965
966template<typename dst_t>
967using dequantize_kq_t = void (*)(const void * vx, const int64_t ib, dst_t * y, const int tid);
968
969static __device__ __forceinline__ float get_alibi_slope(
970    const float max_bias, const uint32_t h, const uint32_t n_head_log2, const float m0, const float m1
971) {
972    if (max_bias <= 0.0f) {
973        return 1.0f;
974    }
975    const float base = h < n_head_log2 ? m0 : m1;
976    const int   exph = h < n_head_log2 ? h + 1 : 2*(h - n_head_log2) + 1;
977
978    return powf(base, exph);
979}
980
981template <ggml_type type>
982struct ggml_cuda_type_traits;
983
984template<>
985struct ggml_cuda_type_traits<GGML_TYPE_F16> {
986    static constexpr int qk = 1;
987    static constexpr int qr = 1;
988    static constexpr int bs = sizeof(ggml_half);
989};
990
991template<>
992struct ggml_cuda_type_traits<GGML_TYPE_Q1_0> {
993    static constexpr int qk = QK1_0;
994    static constexpr int qr = QR1_0;
995    static constexpr int qi = QI1_0;
996    static constexpr int bs = sizeof(block_q1_0);
997};
998
999template<>
1000struct ggml_cuda_type_traits<GGML_TYPE_Q2_0> {
1001    static constexpr int qk = QK2_0;
1002    static constexpr int qr = QR2_0;
1003    static constexpr int qi = QI2_0;
1004    static constexpr int bs = sizeof(block_q2_0);
1005};
1006
1007template<>
1008struct ggml_cuda_type_traits<GGML_TYPE_Q4_0> {
1009    static constexpr int qk = QK4_0;
1010    static constexpr int qr = QR4_0;
1011    static constexpr int qi = QI4_0;
1012    static constexpr int bs = sizeof(block_q4_0);
1013};
1014
1015template<>
1016struct ggml_cuda_type_traits<GGML_TYPE_Q4_1> {
1017    static constexpr int qk = QK4_1;
1018    static constexpr int qr = QR4_1;
1019    static constexpr int qi = QI4_1;
1020    static constexpr int bs = sizeof(block_q4_1);
1021};
1022
1023template<>
1024struct ggml_cuda_type_traits<GGML_TYPE_Q5_0> {
1025    static constexpr int qk = QK5_0;
1026    static constexpr int qr = QR5_0;
1027    static constexpr int qi = QI5_0;
1028    static constexpr int bs = sizeof(block_q5_0);
1029};
1030
1031template<>
1032struct ggml_cuda_type_traits<GGML_TYPE_Q5_1> {
1033    static constexpr int qk = QK5_1;
1034    static constexpr int qr = QR5_1;
1035    static constexpr int qi = QI5_1;
1036    static constexpr int bs = sizeof(block_q5_1);
1037};
1038
1039template<>
1040struct ggml_cuda_type_traits<GGML_TYPE_Q8_0> {
1041    static constexpr int qk = QK8_0;
1042    static constexpr int qr = QR8_0;
1043    static constexpr int qi = QI8_0;
1044    static constexpr int bs = sizeof(block_q8_0);
1045};
1046
1047template<>
1048struct ggml_cuda_type_traits<GGML_TYPE_MXFP4> {
1049    static constexpr int qk = QK_MXFP4;
1050    static constexpr int qr = QR_MXFP4;
1051    static constexpr int qi = QI_MXFP4;
1052    static constexpr int bs = sizeof(block_mxfp4);
1053};
1054
1055template<>
1056struct ggml_cuda_type_traits<GGML_TYPE_NVFP4> {
1057    static constexpr int qk = QK_NVFP4;
1058    static constexpr int qr = QR_NVFP4;
1059    static constexpr int qi = QI_NVFP4;
1060    static constexpr int bs = sizeof(block_nvfp4);
1061};
1062
1063template<>
1064struct ggml_cuda_type_traits<GGML_TYPE_Q2_K> {
1065    static constexpr int qk = QK_K;
1066    static constexpr int qr = QR2_K;
1067    static constexpr int qi = QI2_K;
1068    static constexpr int bs = sizeof(block_q2_K);
1069};
1070
1071template<>
1072struct ggml_cuda_type_traits<GGML_TYPE_Q3_K> {
1073    static constexpr int qk = QK_K;
1074    static constexpr int qr = QR3_K;
1075    static constexpr int qi = QI3_K;
1076    static constexpr int bs = sizeof(block_q3_K);
1077};
1078
1079template<>
1080struct ggml_cuda_type_traits<GGML_TYPE_Q4_K> {
1081    static constexpr int qk = QK_K;
1082    static constexpr int qr = QR4_K;
1083    static constexpr int qi = QI4_K;
1084    static constexpr int bs = sizeof(block_q4_K);
1085};
1086
1087template<>
1088struct ggml_cuda_type_traits<GGML_TYPE_Q5_K> {
1089    static constexpr int qk = QK_K;
1090    static constexpr int qr = QR5_K;
1091    static constexpr int qi = QI5_K;
1092    static constexpr int bs = sizeof(block_q5_K);
1093};
1094
1095template<>
1096struct ggml_cuda_type_traits<GGML_TYPE_Q6_K> {
1097    static constexpr int qk = QK_K;
1098    static constexpr int qr = QR6_K;
1099    static constexpr int qi = QI6_K;
1100    static constexpr int bs = sizeof(block_q6_K);
1101};
1102
1103template<>
1104struct ggml_cuda_type_traits<GGML_TYPE_IQ2_XXS> {
1105    static constexpr int qk = QK_K;
1106    static constexpr int qr = QR2_XXS;
1107    static constexpr int qi = QI2_XXS;
1108    static constexpr int bs = sizeof(block_iq2_xxs);
1109};
1110
1111template<>
1112struct ggml_cuda_type_traits<GGML_TYPE_IQ2_XS> {
1113    static constexpr int qk = QK_K;
1114    static constexpr int qr = QR2_XS;
1115    static constexpr int qi = QI2_XS;
1116    static constexpr int bs = sizeof(block_iq2_xs);
1117};
1118
1119template<>
1120struct ggml_cuda_type_traits<GGML_TYPE_IQ2_S> {
1121    static constexpr int qk = QK_K;
1122    static constexpr int qr = QR2_S;
1123    static constexpr int qi = QI2_S;
1124    static constexpr int bs = sizeof(block_iq2_s);
1125};
1126
1127template<>
1128struct ggml_cuda_type_traits<GGML_TYPE_IQ3_XXS> {
1129    static constexpr int qk = QK_K;
1130    static constexpr int qr = QR3_XXS;
1131    static constexpr int qi = QI3_XXS;
1132    static constexpr int bs = sizeof(block_iq3_xxs);
1133};
1134
1135template<>
1136struct ggml_cuda_type_traits<GGML_TYPE_IQ1_S> {
1137    static constexpr int qk = QK_K;
1138    static constexpr int qr = QR1_S;
1139    static constexpr int qi = QI1_S;
1140    static constexpr int bs = sizeof(block_iq1_s);
1141};
1142
1143template<>
1144struct ggml_cuda_type_traits<GGML_TYPE_IQ1_M> {
1145    static constexpr int qk = QK_K;
1146    static constexpr int qr = QR1_M;
1147    static constexpr int qi = QI1_M;
1148    static constexpr int bs = sizeof(block_iq1_m);
1149};
1150
1151template<>
1152struct ggml_cuda_type_traits<GGML_TYPE_IQ4_NL> {
1153    static constexpr int qk = QK4_NL;
1154    static constexpr int qr = QR4_NL;
1155    static constexpr int qi = QI4_NL;
1156    static constexpr int bs = sizeof(block_iq4_nl);
1157};
1158
1159template<>
1160struct ggml_cuda_type_traits<GGML_TYPE_IQ4_XS> {
1161    static constexpr int qk = QK_K;
1162    static constexpr int qr = QR4_XS;
1163    static constexpr int qi = QI4_XS;
1164    static constexpr int bs = sizeof(block_iq4_xs);
1165};
1166
1167template<>
1168struct ggml_cuda_type_traits<GGML_TYPE_IQ3_S> {
1169    static constexpr int qk = QK_K;
1170    static constexpr int qr = QR3_S;
1171    static constexpr int qi = QI3_S;
1172    static constexpr int bs = sizeof(block_iq3_s);
1173};
1174
1175//////////////////////
1176
1177struct ggml_cuda_device_info {
1178    int device_count;           // number of (possibly virtual) devices exposed to the rest of ggml
1179    int physical_device_count;  // number of physical CUDA devices actually present
1180
1181    struct cuda_device_info {
1182        int     cc;                             // compute capability
1183        int     nsm;                            // number of streaming multiprocessors
1184        size_t  smpb;                           // max. shared memory per block
1185        size_t  smpbo;                          // max. shared memory per block (with opt-in)
1186        bool    integrated;                     // Device is integrated as opposed to discrete
1187        bool    vmm;                            // virtual memory support
1188        size_t  vmm_granularity;                // granularity of virtual memory
1189        size_t  total_vram;
1190        int     warp_size;                      // Number of threads in a dispatch
1191        bool    supports_cooperative_launch;    // whether cooperative launch is supported
1192        int     physical_device;                // backing physical CUDA device for this (virtual) device
1193        int     physical_share_count;           // number of (virtual) devices sharing this device's physical GPU
1194        int     virtual_index;                  // index of this (virtual) device among those sharing its physical GPU
1195    };
1196
1197    cuda_device_info devices[GGML_CUDA_MAX_DEVICES] = {};
1198
1199    std::array<float, GGML_CUDA_MAX_DEVICES> default_tensor_split = {};
1200};
1201
1202const ggml_cuda_device_info & ggml_cuda_info();
1203
1204void ggml_cuda_set_device(int device);
1205int ggml_cuda_get_device();
1206
1207struct ggml_cuda_pool {
1208    virtual ~ggml_cuda_pool() = default;
1209
1210    virtual void * alloc(size_t size, size_t * actual_size) = 0;
1211    virtual void free(void * ptr, size_t size) = 0;
1212};
1213
1214template<typename T>
1215struct ggml_cuda_pool_alloc {
1216    ggml_cuda_pool * pool = nullptr;
1217    T * ptr = nullptr;
1218    size_t actual_size = 0;
1219
1220    ggml_cuda_pool_alloc() = default;
1221
1222    explicit ggml_cuda_pool_alloc(ggml_cuda_pool & pool) : pool(&pool) {
1223    }
1224
1225    ggml_cuda_pool_alloc(ggml_cuda_pool & pool, size_t size) : pool(&pool) {
1226        alloc(size);
1227    }
1228
1229    ~ggml_cuda_pool_alloc() {
1230        if (ptr != nullptr) {
1231            pool->free(ptr, actual_size);
1232        }
1233    }
1234
1235    // size is in number of elements
1236    T * alloc(size_t size) {
1237        GGML_ASSERT(pool != nullptr);
1238        GGML_ASSERT(ptr == nullptr);
1239        ptr = (T *) pool->alloc(size * sizeof(T), &this->actual_size);
1240        return ptr;
1241    }
1242
1243    T * alloc(ggml_cuda_pool & pool, size_t size) {
1244        this->pool = &pool;
1245        return alloc(size);
1246    }
1247
1248    T * get() {
1249        return ptr;
1250    }
1251
1252    ggml_cuda_pool_alloc(const ggml_cuda_pool_alloc &) = delete;
1253    ggml_cuda_pool_alloc(ggml_cuda_pool_alloc &&) = delete;
1254    ggml_cuda_pool_alloc& operator=(const ggml_cuda_pool_alloc &) = delete;
1255    ggml_cuda_pool_alloc& operator=(ggml_cuda_pool_alloc &&) = delete;
1256};
1257
1258
1259// backend interface
1260
1261struct ggml_tensor_extra_gpu {
1262    void * data_device[GGML_CUDA_MAX_DEVICES]; // 1 pointer for each device for split tensors
1263    cudaEvent_t events[GGML_CUDA_MAX_DEVICES][GGML_CUDA_MAX_STREAMS]; // events for synchronizing multiple GPUs
1264};
1265
1266
1267#if (defined(GGML_CUDA_USE_GRAPHS) || defined(GGML_HIP_GRAPHS)) || defined(GGML_MUSA_GRAPHS)
1268#define USE_CUDA_GRAPH
1269#endif
1270
1271struct ggml_cuda_graph {
1272#ifdef USE_CUDA_GRAPH
1273    ~ggml_cuda_graph() {
1274        if (instance != nullptr) {
1275            CUDA_CHECK(cudaGraphExecDestroy(instance));
1276        }
1277        if (graph != nullptr) {
1278            CUDA_CHECK(cudaGraphDestroy(graph));
1279        }
1280    }
1281    cudaGraph_t graph = nullptr;
1282    cudaGraphExec_t instance = nullptr;
1283    size_t num_nodes = 0;
1284    std::vector<cudaGraphNode_t> nodes;
1285    bool disable_due_to_gpu_arch = false;
1286    bool warmup_complete = false;
1287    uint64_t uid = 0;
1288    int64_t last_used_time = 0;
1289    struct node_properties {
1290        ggml_tensor node;
1291        void *   node_src_data_ptrs[GGML_MAX_SRC];
1292        int64_t  node_src_ne[GGML_MAX_SRC][GGML_MAX_DIMS];
1293        size_t   node_src_nb[GGML_MAX_SRC][GGML_MAX_DIMS];
1294    };
1295    std::vector<node_properties> node_props;
1296
1297    bool is_enabled() const {
1298        static const bool disable_cuda_graphs_due_to_env = (getenv("GGML_CUDA_DISABLE_GRAPHS") != nullptr);
1299        return !(disable_due_to_gpu_arch || disable_cuda_graphs_due_to_env);
1300    }
1301#endif
1302};
1303
1304struct ggml_cuda_concurrent_event {
1305    std::vector<cudaEvent_t> join_events;
1306    cudaEvent_t              fork_event = nullptr;
1307
1308    int                                          n_streams = 0;
1309    std::unordered_map<const ggml_tensor *, int> stream_mapping;
1310
1311    // Original order of nodes in this concurrent region (before interleaving)
1312    // Used to restore grouping for fusion within streams
1313    std::vector<const ggml_tensor *> original_order;
1314
1315    const ggml_tensor * join_node;
1316
1317    ggml_cuda_concurrent_event() = default;
1318
1319    ggml_cuda_concurrent_event(const ggml_cuda_concurrent_event &) = delete;
1320    ggml_cuda_concurrent_event & operator=(const ggml_cuda_concurrent_event &) = delete;
1321
1322    explicit ggml_cuda_concurrent_event(int n_streams) : n_streams(n_streams) {
1323        join_events.resize(n_streams);
1324
1325        for (size_t i = 0; i < join_events.size(); ++i) {
1326            CUDA_CHECK(cudaEventCreateWithFlags(&join_events[i], cudaEventDisableTiming));
1327        }
1328
1329        CUDA_CHECK(cudaEventCreateWithFlags(&fork_event, cudaEventDisableTiming));
1330    }
1331
1332    ggml_cuda_concurrent_event(ggml_cuda_concurrent_event && other) noexcept
1333    : join_events(std::move(other.join_events))
1334    , fork_event(other.fork_event)
1335    , n_streams(other.n_streams)
1336    , stream_mapping(std::move(other.stream_mapping))
1337    , original_order(std::move(other.original_order))
1338    , join_node(other.join_node) {
1339        other.fork_event = nullptr;
1340    }
1341
1342    // 1. check if any branches write to overlapping memory ranges (except the join node)
1343    // 2. check whether all srcs are either within the branch or outside the nodes covered by ggml_cuda_concurrent_event
1344    // we assume all nodes have the same buffer
1345    bool is_valid() const {
1346        std::vector<std::vector<std::pair<int64_t, int64_t>>> write_ranges;
1347        write_ranges.resize(n_streams);
1348
1349        // get join_node's memory range to exclude from overlap checking.
1350        // multiple nodes can use join_node's buffer; we synchronize on the join node.
1351        const ggml_tensor * join_t     = join_node->view_src ? join_node->view_src : join_node;
1352        const int64_t       join_start = (int64_t) join_t->data;
1353        const int64_t       join_end   = join_start + ggml_nbytes(join_t);
1354
1355        for (const auto & [tensor, stream] : stream_mapping) {
1356            const ggml_tensor * t = tensor->view_src ? tensor->view_src : tensor;
1357            const int64_t       t_start = (int64_t) t->data;
1358            const int64_t       t_end   = t_start + ggml_nbytes(t);
1359
1360            // skip tensors that overlap with join_node's buffer.
1361            if ((t_start <= join_start && join_start < t_end) || (join_start <= t_start && t_start < join_end)) {
1362                continue;
1363            }
1364
1365            // concurrent streams begin from 1
1366            write_ranges[stream - 1].emplace_back(t_start, t_end);
1367        }
1368
1369        for (int i = 0; i < n_streams; ++i) {
1370            // sorts first by start then by end of write range
1371            std::sort(write_ranges[i].begin(), write_ranges[i].end());
1372        }
1373
1374        bool writes_overlap = false;
1375        bool dependent_srcs = false;
1376        for (const auto & [tensor, stream] : stream_mapping) {
1377            const ggml_tensor * t = tensor->view_src ? tensor->view_src : tensor;
1378            const int64_t       t_start = (int64_t) t->data;
1379            const int64_t       t_end   = t_start + ggml_nbytes(t);
1380
1381            // skip tensors that overlap with join_node's buffer
1382            if ((t_start <= join_start && join_start < t_end) || (join_start <= t_start && t_start < join_end)) {
1383                continue;
1384            }
1385
1386            // check if this buffer's write data overlaps with another stream's
1387            std::pair<int64_t, int64_t> data_range = std::make_pair(t_start, t_end);
1388            for (int i = 0; i < n_streams; ++i) {
1389                if (i == stream - 1) {
1390                    continue;
1391                }
1392                auto it = std::lower_bound(write_ranges[i].begin(), write_ranges[i].end(), data_range);
1393
1394                if (it != write_ranges[i].end()) {
1395                    const std::pair<int64_t, int64_t> & other = *it;
1396
1397                    // std::lower_bound returns the first element where other >= data_range (lexicographically).
1398                    // This guarantees other.first >= data_range.first.
1399                    // Therefore, overlap occurs iff other.first < data_range.second
1400                    // (i.e., the other range starts before this range ends).
1401                    if (other.first < data_range.second) {
1402                        GGML_LOG_DEBUG("Writes overlap for %s", tensor->name);
1403                        writes_overlap = true;
1404                        break;
1405                    }
1406                }
1407            }
1408
1409            //check if all srcs are either in branch or don't have a branch
1410            for (int i = 0; i < GGML_MAX_SRC; ++i) {
1411                if (!tensor->src[i]) {
1412                    continue;
1413                }
1414
1415                auto it = stream_mapping.find(tensor->src[i]);
1416
1417                if (it == stream_mapping.end()) {
1418                    continue;
1419                }
1420
1421                if (it->second != stream) {
1422                    dependent_srcs = true;
1423                    break;
1424                }
1425            }
1426
1427            if (dependent_srcs || writes_overlap) {
1428                break;
1429            }
1430        }
1431
1432        return !writes_overlap && !dependent_srcs;
1433    }
1434
1435    ~ggml_cuda_concurrent_event() {
1436        if (fork_event != nullptr) {
1437            CUDA_CHECK(cudaEventDestroy(fork_event));
1438        }
1439        for (cudaEvent_t e : join_events) {
1440            if (e != nullptr) {
1441                CUDA_CHECK(cudaEventDestroy(e));
1442            }
1443        }
1444    }
1445};
1446
1447struct ggml_cuda_stream_context {
1448    std::unordered_map<const ggml_tensor *, ggml_cuda_concurrent_event> concurrent_events;
1449
1450    void reset() {
1451        concurrent_events.clear();
1452    }
1453};
1454
1455struct ggml_backend_cuda_context {
1456    int device;
1457    std::string name;
1458    cudaEvent_t copy_event = nullptr;
1459
1460    cudaStream_t streams[GGML_CUDA_MAX_DEVICES][GGML_CUDA_MAX_STREAMS] = { { nullptr } };
1461    cublasHandle_t cublas_handles[GGML_CUDA_MAX_DEVICES][GGML_CUDA_MAX_STREAMS] = {nullptr};
1462    void * cublas_workspaces[GGML_CUDA_MAX_DEVICES][GGML_CUDA_MAX_STREAMS] = {nullptr};
1463    size_t cublas_workspace_sizes[GGML_CUDA_MAX_DEVICES] = {0};
1464
1465    int curr_stream_no = 0;
1466
1467#ifdef USE_CUDA_GRAPH
1468    // Map from first_node_ptr to cuda_graph - allows multiple graphs per context
1469    // when the computation is split across CPU/GPU (e.g., with --n-cpu-moe)
1470    std::unordered_map<const void *, std::unique_ptr<ggml_cuda_graph>> cuda_graphs;
1471
1472    int64_t last_graph_eviction_sweep = 0;
1473
1474    ggml_cuda_graph * cuda_graph(const void * first_node_ptr) {
1475        const int64_t time_now = ggml_time_us();
1476
1477        // sweep every 5s, evicting cuda graphs unused for >=10s
1478        if (time_now - last_graph_eviction_sweep >= 5'000'000) {
1479            last_graph_eviction_sweep = time_now;
1480            for (auto it = cuda_graphs.begin(); it != cuda_graphs.end(); ) {
1481                if (time_now - it->second->last_used_time >= 10'000'000) {
1482                    it = cuda_graphs.erase(it);
1483                } else {
1484                    ++it;
1485                }
1486            }
1487        }
1488
1489        auto it = cuda_graphs.find(first_node_ptr);
1490        if (it == cuda_graphs.end()) {
1491            it = cuda_graphs.emplace(first_node_ptr, std::make_unique<ggml_cuda_graph>()).first;
1492        }
1493        it->second->last_used_time = time_now;
1494        return it->second.get();
1495    }
1496
1497    // Check if any CUDA graph is enabled for this context (used by kernels that need to know
1498    // if graphs are in use without having access to the specific graph key)
1499    bool any_cuda_graph_enabled() const {
1500        for (const auto & [key, graph] : cuda_graphs) {
1501            if (graph && graph->is_enabled()) {
1502                return true;
1503            }
1504        }
1505        return false;
1506    }
1507
1508    // Check if any CUDA graph has an instance for this context
1509    bool any_cuda_graph_has_instance() const {
1510        for (const auto & [key, graph] : cuda_graphs) {
1511            if (graph && graph->instance != nullptr) {
1512                return true;
1513            }
1514        }
1515        return false;
1516    }
1517#endif // USE_CUDA_GRAPH
1518
1519    explicit ggml_backend_cuda_context(int device) :
1520        device(device),
1521        name(GGML_CUDA_NAME + std::to_string(device)) {
1522    }
1523
1524    ggml_cuda_stream_context concurrent_stream_context;
1525
1526    ~ggml_backend_cuda_context();
1527
1528    cudaStream_t stream(int device, int stream) {
1529        if (streams[device][stream] == nullptr) {
1530            ggml_cuda_set_device(device);
1531            CUDA_CHECK(cudaStreamCreateWithFlags(&streams[device][stream], cudaStreamNonBlocking));
1532        }
1533        return streams[device][stream];
1534    }
1535
1536    cudaStream_t stream() { return stream(device, curr_stream_no); }
1537
1538    ggml_cuda_stream_context & stream_context() { return concurrent_stream_context; }
1539
1540    cublasHandle_t cublas_handle() {
1541        if (cublas_handles[device][curr_stream_no] == nullptr) {
1542            ggml_cuda_set_device(device);
1543            CUBLAS_CHECK(cublasCreate(&cublas_handles[device][curr_stream_no]));
1544            CUBLAS_CHECK(cublasSetMathMode(cublas_handles[device][curr_stream_no], CUBLAS_TF32_TENSOR_OP_MATH));
1545            CUBLAS_CHECK(cublasSetStream(cublas_handles[device][curr_stream_no], stream()));
1546#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA) && (CUBLAS_VER_MAJOR > 11 || (CUBLAS_VER_MAJOR == 11 && CUBLAS_VER_MINOR >= 2))
1547            if (cublas_workspace_sizes[device] == 0) {
1548                const int cc = ggml_cuda_info().devices[device].cc;
1549                cublas_workspace_sizes[device] = (cc >= GGML_CUDA_CC_HOPPER) ? 32 * 1024 * 1024 : 4 * 1024 * 1024;
1550            }
1551            CUDA_CHECK(cudaMalloc(&cublas_workspaces[device][curr_stream_no], cublas_workspace_sizes[device]));
1552            CUBLAS_CHECK(cublasSetWorkspace(cublas_handles[device][curr_stream_no], cublas_workspaces[device][curr_stream_no], cublas_workspace_sizes[device]));
1553#endif
1554        }
1555        return cublas_handles[device][curr_stream_no];
1556    }
1557
1558    // pool
1559    std::unique_ptr<ggml_cuda_pool> pools[GGML_CUDA_MAX_DEVICES][GGML_CUDA_MAX_STREAMS];
1560
1561    static std::unique_ptr<ggml_cuda_pool> new_pool_for_device(int device, int stream_no);
1562
1563    ggml_cuda_pool & pool(int device) {
1564        if (pools[device][curr_stream_no] == nullptr) {
1565            pools[device][curr_stream_no] = new_pool_for_device(device, curr_stream_no);
1566        }
1567        return *pools[device][curr_stream_no];
1568    }
1569
1570    ggml_cuda_pool & pool() {
1571        return pool(device);
1572    }
1573};
1574
1575struct ggml_cuda_mm_fusion_args_host {
1576    const ggml_tensor * x_bias = nullptr;
1577    const ggml_tensor * gate = nullptr;
1578    const ggml_tensor * gate_bias = nullptr;
1579    const ggml_tensor * x_scale = nullptr;
1580    const ggml_tensor * gate_scale = nullptr;
1581    ggml_glu_op glu_op;
1582    float glu_limit = 0.0f;
1583};
1584struct ggml_cuda_mm_fusion_args_device {
1585    const void * x_bias = nullptr;
1586    const void * gate = nullptr;
1587    const void * gate_bias = nullptr;
1588    const void * x_scale = nullptr;
1589    const void * gate_scale = nullptr;
1590    ggml_glu_op glu_op;
1591    float glu_limit = 0.0f;
1592};
1593
1594struct ggml_cuda_kernel_launch_params {
1595    dim3 block_nums;
1596    dim3 block_dims;
1597    size_t shmem;
1598    cudaStream_t stream;
1599
1600    // size_t shmem
1601    ggml_cuda_kernel_launch_params(const dim3& block_nums_, const dim3& block_dims_, const size_t shmem_, const cudaStream_t stream_)
1602        : block_nums(block_nums_), block_dims(block_dims_), shmem(shmem_), stream(stream_) {}
1603
1604    // Some call sites pass ints instead of the required size_t. This 2nd constructor casts int->size_t to avoid these -Wnarrowing warnings.
1605    ggml_cuda_kernel_launch_params(const dim3& block_nums_, const dim3& block_dims_, const int shmem_, const cudaStream_t stream_)
1606        : block_nums(block_nums_), block_dims(block_dims_), shmem((size_t)shmem_), stream(stream_) {}
1607};
1608
1609#if defined(GGML_CUDA_USE_PDL)
1610struct ggml_cuda_pdl_config {
1611    cudaLaunchAttribute attr;
1612    cudaLaunchConfig_t  cfg;
1613
1614    ggml_cuda_pdl_config(const ggml_cuda_kernel_launch_params & params) {
1615        attr.id = cudaLaunchAttributeProgrammaticStreamSerialization;
1616        attr.val.programmaticStreamSerializationAllowed = 1;
1617
1618        cfg = {};
1619        cfg.gridDim          = params.block_nums;
1620        cfg.blockDim         = params.block_dims;
1621        cfg.dynamicSmemBytes = params.shmem;
1622        cfg.stream           = params.stream;
1623        cfg.attrs            = &attr;
1624        cfg.numAttrs         = 1;
1625    }
1626
1627    // Delete due to &attr
1628    ggml_cuda_pdl_config(const ggml_cuda_pdl_config&) = delete;
1629    ggml_cuda_pdl_config& operator=(const ggml_cuda_pdl_config&) = delete;
1630    ggml_cuda_pdl_config& operator=(ggml_cuda_pdl_config&&) = delete;
1631
1632};
1633
1634static bool ggml_cuda_kernel_can_use_pdl(const void * kernel) {
1635    const int device = ggml_cuda_get_device();
1636
1637    struct cache_key {
1638        int          device;
1639        const void * kernel;
1640
1641        bool operator==(const cache_key & other) const { return device == other.device && kernel == other.kernel; }
1642    };
1643
1644    struct cache_key_hash {
1645        // MurmurHash3 mixing function for better hash distribution (vs. just std::hash which in some implementations simply returns the identity)
1646        static size_t hash_mix(size_t x) {
1647            std::uint64_t       y = x;
1648            const std::uint64_t m = 0xe9846af9b1a615d;
1649
1650            y ^= y >> 32;
1651            y *= m;
1652            y ^= y >> 32;
1653            y *= m;
1654            y ^= y >> 28;
1655
1656            return static_cast<size_t>(y);
1657        }
1658
1659        size_t operator()(const cache_key & key) const {
1660            // Use a nonzero seed to avoid mapping all-zero keys to zero
1661            size_t h = 42;
1662            h        = hash_mix(h + key.device);
1663            h        = hash_mix(h + reinterpret_cast<size_t>(key.kernel));
1664            return h;
1665        }
1666    };
1667
1668    static std::mutex                                          cache_mutex;
1669    static std::unordered_map<cache_key, bool, cache_key_hash> cache;
1670
1671    const cache_key             key = { device, kernel };
1672    std::lock_guard<std::mutex> lock(cache_mutex);
1673    const auto                  it = cache.find(key);
1674    if (it != cache.end()) {
1675        return it->second;
1676    }
1677
1678    cudaFuncAttributes attr = {};
1679    CUDA_CHECK(cudaFuncGetAttributes(&attr, kernel));
1680
1681    // PDL device-side primitives are emitted only for PTX versions >= 90.
1682    // We have to guard on a loaded kernel's PTX version so a kernel forward-JIT'ed
1683    // from pre-Hopper PTX to a Hopper-or-newer GPU does not opt into PDL.
1684    const bool can_use_pdl = attr.ptxVersion >= 90;
1685    cache.emplace(key, can_use_pdl);
1686    return can_use_pdl;
1687}
1688
1689#endif //defined(GGML_CUDA_USE_PDL)
1690
1691// PDL and __restrict__ need to be mutually exclusive, see https://github.com/ggml-org/llama.cpp/pull/24030
1692# if (defined(GGML_CUDA_USE_PDL) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_HOPPER)
1693# define GGML_CUDA_RESTRICT
1694# else
1695# define GGML_CUDA_RESTRICT __restrict__
1696# endif // defined(GGML_CUDA_USE_PDL) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_HOPPER
1697
1698template<typename Kernel, typename... Args>
1699static __inline__ void ggml_cuda_kernel_launch(Kernel kernel, const ggml_cuda_kernel_launch_params & launch_params, Args&&... args) {
1700#if defined(GGML_CUDA_USE_PDL)
1701
1702    static const bool env_pdl_enabled = []() {
1703        const char * env = getenv("GGML_CUDA_PDL");
1704        return env == nullptr || std::atoi(env) != 0;
1705    }();
1706
1707    if (env_pdl_enabled && ggml_cuda_kernel_can_use_pdl(reinterpret_cast<const void *>(kernel))) {
1708        auto pdl_cfg = ggml_cuda_pdl_config(launch_params);
1709
1710        CUDA_CHECK(cudaLaunchKernelEx(&pdl_cfg.cfg, kernel, std::forward<Args>(args)... ));
1711        return;
1712    }
1713#endif //defined(GGML_CUDA_USE_PDL)
1714
1715    kernel<<<launch_params.block_nums, launch_params.block_dims, launch_params.shmem, launch_params.stream>>>(std::forward<Args>(args)... );
1716    CUDA_CHECK(cudaGetLastError());
1717}