char-fork/llama.cpp

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

Rafail GiavrimisCUDA: fix thread/block count in quantized cpy kernel launches (#26731)69bf64379

char/aliceai-t5-moe
30.8 KiB617 linesraw
1#include "cpy.cuh"
2#include "dequantize.cuh"
3#include "cpy-utils.cuh"
4#if defined(GGML_USE_MUSA) && defined(GGML_MUSA_MUDNN_COPY)
5#include "ggml-musa/mudnn.cuh"
6#endif // GGML_USE_MUSA && GGML_MUSA_MUDNN_COPY
7
8typedef void (*cpy_kernel_t)(const char * cx, char * cdst);
9
10const int CUDA_CPY_TILE_DIM_2D = 32; // 2D tile dimension for transposed blocks
11const int CUDA_CPY_BLOCK_NM = 8;     // block size of 3rd dimension if available
12const int CUDA_CPY_BLOCK_ROWS = 8;   // block dimension for marching through rows
13
14template <cpy_kernel_t cpy_1>
15static __global__ void cpy_scalar(const char * cx, char * cdst, const int64_t ne,
16                                  const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
17                                  const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11,
18                                  const int64_t nb12, const int64_t nb13) {
19    ggml_cuda_pdl_lc();
20    const int64_t i = (int64_t)blockDim.x*blockIdx.x + threadIdx.x;
21
22    if (i >= ne) {
23        return;
24    }
25
26    // determine indices i03/i13, i02/i12, i01/i11, i00/i10 as a function of index i of flattened tensor
27    // then combine those indices with the corresponding byte offsets to get the total offsets
28    const int64_t i03 = i/(ne00 * ne01 * ne02);
29    const int64_t i02 = (i - i03*ne00*ne01*ne02 )/ (ne00*ne01);
30    const int64_t i01 = (i - i03*ne00*ne01*ne02  -  i02*ne01*ne00) / ne00;
31    const int64_t i00 = i - i03*ne00*ne01*ne02 - i02*ne01*ne00 - i01*ne00;
32    const int64_t x_offset = i00*nb00 + i01*nb01 + i02*nb02 + i03 * nb03;
33
34    const int64_t i13 = i/(ne10 * ne11 * ne12);
35    const int64_t i12 = (i - i13*ne10*ne11*ne12) / (ne10*ne11);
36    const int64_t i11 = (i - i13*ne10*ne11*ne12 - i12*ne10*ne11) / ne10;
37    const int64_t i10 = i - i13*ne10*ne11*ne12 - i12*ne10*ne11 - i11*ne10;
38    const int64_t dst_offset = i10*nb10 + i11*nb11 + i12*nb12 + i13 * nb13;
39
40    ggml_cuda_pdl_sync();
41    cpy_1(cx + x_offset, cdst + dst_offset);
42}
43
44template <typename T>
45static __global__ void cpy_scalar_transpose(const char * cx, char * cdst, const int64_t ne,
46                               const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
47                               const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11,
48                               const int64_t nb12, const int64_t nb13) {
49
50    const T* src = reinterpret_cast<const T*>(cx);
51    T* dst = reinterpret_cast<T*>(cdst);
52
53    const int64_t nmat = ne / (ne00 * ne01);
54    const int64_t n = ne00 * ne01;
55
56    const int64_t x  = (int64_t) blockIdx.x * CUDA_CPY_TILE_DIM_2D + threadIdx.x;
57    const int64_t y  = (int64_t) blockIdx.y * CUDA_CPY_TILE_DIM_2D + threadIdx.y;
58    const int64_t tx = (int64_t) blockIdx.y * CUDA_CPY_TILE_DIM_2D + threadIdx.x;  // transpose block offset
59    const int64_t ty = (int64_t) blockIdx.x * CUDA_CPY_TILE_DIM_2D + threadIdx.y;
60
61    __shared__ float tile[2][CUDA_CPY_TILE_DIM_2D][CUDA_CPY_TILE_DIM_2D+1];
62    int cur_tile_buf = 0;
63
64    ggml_cuda_pdl_sync();
65#pragma unroll
66    for (int i = 0; i < CUDA_CPY_BLOCK_NM; ++i) {
67
68        const unsigned int imat = blockIdx.z * CUDA_CPY_BLOCK_NM + i;
69        if (imat >= nmat)
70            break;
71
72#pragma unroll
73        for (int j = 0; j < CUDA_CPY_TILE_DIM_2D; j += CUDA_CPY_BLOCK_ROWS) {
74            if(x < ne01 && y + j < ne00){
75                const int row = threadIdx.y+j;
76                const int col = threadIdx.x * sizeof(float)/sizeof(T);
77                T *tile2 = reinterpret_cast<T*>(tile[cur_tile_buf][row]);
78                tile2[col] = src[imat*n + (y+j)*ne01 + x];
79            }
80        }
81
82        __syncthreads();
83
84#pragma unroll
85        for (int j = 0; j < CUDA_CPY_TILE_DIM_2D; j += CUDA_CPY_BLOCK_ROWS) {
86            if (ty + j < ne01 && tx < ne00) {
87                const int col = (threadIdx.y+j)*sizeof(float)/sizeof(T);
88                const T *tile2 = reinterpret_cast<const T*>(tile[cur_tile_buf][threadIdx.x]);
89                dst[imat*n + (ty+j)*ne00 + tx] = tile2[col];
90            }
91        }
92
93        cur_tile_buf = (cur_tile_buf + 1) % 2;
94    }
95
96    GGML_UNUSED_VARS(ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11,
97        nb12, nb13);
98}
99
100static __device__ void cpy_blck_q8_0_f32(const char * cxi, char * cdsti) {
101    float * cdstf = (float *)(cdsti);
102
103#pragma unroll
104    for (int j = 0; j < QK8_0; j += 2) {
105        float2 dq;
106        dequantize_q8_0(cxi, 0, j, dq);
107        *(cdstf + j) = dq.x;
108        *(cdstf + j + 1) = dq.y;
109    }
110}
111
112template<dequantize_kernel_t dequant, int qk>
113static __device__ void cpy_blck_q_f32(const char * cxi, char * cdsti) {
114    float * cdstf = (float *)(cdsti);
115
116#pragma unroll
117    for (int j = 0; j < qk/2; j++) {
118        float2 dq;
119        dequant(cxi, 0, j, dq);
120        *(cdstf + j) = dq.x;
121        *(cdstf + j + qk/2) = dq.y;
122    }
123}
124
125template <cpy_kernel_t cpy_blck, int qk>
126static __global__ void cpy_f32_q(const char * cx, char * cdst, const int64_t ne,
127                                 const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
128                                 const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11,
129                                 const int64_t nb12, const int64_t nb13) {
130    const int64_t i = ((int64_t)blockDim.x*blockIdx.x + threadIdx.x)*qk;
131
132    if (i >= ne) {
133        return;
134    }
135
136    const int64_t i03 = i/(ne00 * ne01 * ne02);
137    const int64_t i02 = (i - i03*ne00*ne01*ne02 )/ (ne00*ne01);
138    const int64_t i01 = (i - i03*ne00*ne01*ne02  -  i02*ne01*ne00) / ne00;
139    const int64_t i00 = i - i03*ne00*ne01*ne02 - i02*ne01*ne00 - i01*ne00;
140    const int64_t x_offset = i00*nb00 + i01*nb01 + i02*nb02 + i03 * nb03;
141
142    const int64_t i13 = i/(ne10 * ne11 * ne12);
143    const int64_t i12 = (i - i13*ne10*ne11*ne12) / (ne10*ne11);
144    const int64_t i11 = (i - i13*ne10*ne11*ne12 - i12*ne10*ne11) / ne10;
145    const int64_t i10 = i - i13*ne10*ne11*ne12 - i12*ne10*ne11 - i11*ne10;
146    const int64_t dst_offset = (i10/qk)*nb10 + i11*nb11 + i12*nb12 + i13*nb13;
147
148    ggml_cuda_pdl_sync();
149    cpy_blck(cx + x_offset, cdst + dst_offset);
150}
151
152template <cpy_kernel_t cpy_blck, int qk>
153static __global__ void cpy_q_f32(const char * cx, char * cdst, const int64_t ne,
154                                 const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
155                                 const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11,
156                                 const int64_t nb12, const int64_t nb13) {
157    const int64_t i = ((int64_t)blockDim.x*blockIdx.x + threadIdx.x)*qk;
158
159    if (i >= ne) {
160        return;
161    }
162
163    const int64_t i03 = i/(ne00 * ne01 * ne02);
164    const int64_t i02 = (i - i03*ne00*ne01*ne02 )/ (ne00*ne01);
165    const int64_t i01 = (i - i03*ne00*ne01*ne02  -  i02*ne01*ne00) / ne00;
166    const int64_t i00 = i - i03*ne00*ne01*ne02 - i02*ne01*ne00 - i01*ne00;
167    const int64_t x_offset = (i00/qk)*nb00 + i01*nb01 + i02*nb02 + i03 * nb03;
168
169    const int64_t i13 = i/(ne10 * ne11 * ne12);
170    const int64_t i12 = (i - i13*ne10*ne11*ne12) / (ne10*ne11);
171    const int64_t i11 = (i - i13*ne10*ne11*ne12 - i12*ne10*ne11) / ne10;
172    const int64_t i10 = i - i13*ne10*ne11*ne12 - i12*ne10*ne11 - i11*ne10;
173    const int64_t dst_offset = i10*nb10 + i11*nb11 + i12*nb12 + i13*nb13;
174
175    ggml_cuda_pdl_sync();
176    cpy_blck(cx + x_offset, cdst + dst_offset);
177}
178
179template<typename src_t, typename dst_t>
180static __global__ void cpy_scalar_contiguous(const char * cx, char * cdst, const int64_t ne) {
181    const int64_t i = (int64_t)blockDim.x*blockIdx.x + threadIdx.x;
182
183    if (i >= ne) {
184        return;
185    }
186
187    const src_t * x = (const src_t *) cx;
188    dst_t *     dst = (dst_t *) cdst;
189
190    ggml_cuda_pdl_sync();
191    dst[i] = ggml_cuda_cast<dst_t>(x[i]);
192}
193
194template<typename src_t, typename dst_t>
195static void ggml_cpy_scalar_contiguous_cuda(
196    const char * cx, char * cdst, const int64_t ne,
197cudaStream_t stream) {
198
199    const int64_t num_blocks = (ne + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
200    GGML_ASSERT(num_blocks <= INT_MAX);
201    const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params((dim3)num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream);
202    ggml_cuda_kernel_launch(cpy_scalar_contiguous<src_t, dst_t>, launch_params, cx, cdst, ne);
203}
204
205template<typename src_t, typename dst_t, bool transposed = false>
206static void ggml_cpy_scalar_cuda(
207    const char * cx, char * cdst, const int64_t ne,
208    const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
209    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13, cudaStream_t stream) {
210
211    const auto launch_scalar_generic = [&]() {
212        const int64_t num_blocks = (ne + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
213        GGML_ASSERT(num_blocks <= INT_MAX);
214        const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params((dim3)num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream);
215        ggml_cuda_kernel_launch(cpy_scalar<cpy_1_scalar<src_t, dst_t>>, launch_params,
216            cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
217    };
218
219    if (transposed) {
220        GGML_ASSERT(ne == ne00*ne01*ne02);  // ne[3] is 1 assumed
221        int64_t ne00n, ne01n, ne02n;
222        if (nb00 <= nb02) { // most likely safe to handle nb00 = nb02 case here
223            ne00n = ne00;
224            ne01n = ne01;
225            ne02n = ne02;
226        } else {
227            ne00n = ne00;
228            ne01n = ne01*ne02;
229            ne02n = 1;
230        }
231
232        int64_t grid_x = (ne01n + CUDA_CPY_TILE_DIM_2D - 1) / CUDA_CPY_TILE_DIM_2D;
233        int64_t grid_y = (ne00n + CUDA_CPY_TILE_DIM_2D - 1) / CUDA_CPY_TILE_DIM_2D;
234        int64_t grid_z = (ne/(ne01n*ne00n) + CUDA_CPY_BLOCK_NM - 1) / CUDA_CPY_BLOCK_NM;
235        GGML_ASSERT(grid_x <= INT_MAX);
236        if (grid_y > USHRT_MAX || grid_z > USHRT_MAX) {
237            launch_scalar_generic();
238        } else {
239            dim3 dimGrid(grid_x, grid_y, grid_z);
240            dim3 dimBlock(CUDA_CPY_TILE_DIM_2D, CUDA_CPY_BLOCK_ROWS, 1);
241            const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(dimGrid, dimBlock, 0, stream);
242            ggml_cuda_kernel_launch(cpy_scalar_transpose<dst_t>, launch_params,
243                cx, cdst, ne, ne00n, ne01n, ne02n, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
244        }
245    } else {
246        launch_scalar_generic();
247    }
248}
249
250static void ggml_cpy_f32_q8_0_cuda(
251    const char * cx, char * cdst, const int64_t ne,
252    const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
253    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13, cudaStream_t stream) {
254
255    GGML_ASSERT(ne % QK8_0 == 0);
256    const int64_t num_blocks = (ne/QK8_0 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
257    GGML_ASSERT(num_blocks <= INT_MAX);
258    cpy_f32_q<cpy_blck_f32_q8_0, QK8_0><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>
259        (cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
260}
261
262static void ggml_cpy_q8_0_f32_cuda(
263    const char * cx, char * cdst, const int64_t ne,
264    const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
265    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13, cudaStream_t stream) {
266
267    const int64_t num_blocks = (ne/QK8_0 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
268    GGML_ASSERT(num_blocks <= INT_MAX);
269    cpy_q_f32<cpy_blck_q8_0_f32, QK8_0><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>
270        (cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
271}
272
273static void ggml_cpy_f32_q4_0_cuda(
274    const char * cx, char * cdst, const int64_t ne,
275    const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
276    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13, cudaStream_t stream) {
277
278    GGML_ASSERT(ne % QK4_0 == 0);
279    const int64_t num_blocks = (ne/QK4_0 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
280    GGML_ASSERT(num_blocks <= INT_MAX);
281    cpy_f32_q<cpy_blck_f32_q4_0, QK4_0><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>
282        (cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
283}
284
285static void ggml_cpy_q4_0_f32_cuda(
286    const char * cx, char * cdst, const int64_t ne,
287    const int64_t ne00, const int64_t ne01, const int64_t ne02,
288    const int64_t nb00, const int64_t nb01, const int64_t nb02,
289    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12,
290    const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13,
291    cudaStream_t stream) {
292    const int64_t num_blocks = (ne/QK4_0 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
293    GGML_ASSERT(num_blocks <= INT_MAX);
294    cpy_q_f32<cpy_blck_q_f32<dequantize_q4_0, QK4_0>, QK4_0><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>(
295        cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03,
296         ne10, ne11, ne12, nb10, nb11, nb12, nb13);
297}
298
299static void ggml_cpy_f32_q4_1_cuda(
300    const char * cx, char * cdst, const int64_t ne,
301    const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
302    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13, cudaStream_t stream) {
303
304    GGML_ASSERT(ne % QK4_1 == 0);
305    const int64_t num_blocks = (ne/QK4_1 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
306    GGML_ASSERT(num_blocks <= INT_MAX);
307    cpy_f32_q<cpy_blck_f32_q4_1, QK4_1><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>
308        (cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
309}
310
311static void ggml_cpy_q4_1_f32_cuda(
312    const char * cx, char * cdst, const int64_t ne,
313    const int64_t ne00, const int64_t ne01, const int64_t ne02,
314    const int64_t nb00, const int64_t nb01, const int64_t nb02,
315    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12,
316    const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13,
317    cudaStream_t stream) {
318    const int64_t num_blocks = (ne/QK4_1 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
319    GGML_ASSERT(num_blocks <= INT_MAX);
320    cpy_q_f32<cpy_blck_q_f32<dequantize_q4_1, QK4_1>, QK4_1><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>(
321        cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03,
322         ne10, ne11, ne12, nb10, nb11, nb12, nb13);
323}
324
325static void ggml_cpy_f32_q5_0_cuda(
326    const char * cx, char * cdst, const int64_t ne,
327    const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
328    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13, cudaStream_t stream) {
329
330    GGML_ASSERT(ne % QK5_0 == 0);
331    const int64_t num_blocks = (ne/QK5_0 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
332    GGML_ASSERT(num_blocks <= INT_MAX);
333    cpy_f32_q<cpy_blck_f32_q5_0, QK5_0><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>
334        (cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
335}
336
337static void ggml_cpy_q5_0_f32_cuda(
338    const char * cx, char * cdst, const int64_t ne,
339    const int64_t ne00, const int64_t ne01, const int64_t ne02,
340    const int64_t nb00, const int64_t nb01, const int64_t nb02,
341    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12,
342    const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13,
343    cudaStream_t stream) {
344    const int64_t num_blocks = (ne/QK5_0 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
345    GGML_ASSERT(num_blocks <= INT_MAX);
346    cpy_q_f32<cpy_blck_q_f32<dequantize_q5_0, QK5_0>, QK5_0><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>(
347        cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03,
348        ne10, ne11, ne12, nb10, nb11, nb12, nb13);
349}
350
351static void ggml_cpy_f32_q5_1_cuda(
352    const char * cx, char * cdst, const int64_t ne,
353    const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
354    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13, cudaStream_t stream) {
355
356    GGML_ASSERT(ne % QK5_1 == 0);
357    const int64_t num_blocks = (ne/QK5_1 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
358    GGML_ASSERT(num_blocks <= INT_MAX);
359    cpy_f32_q<cpy_blck_f32_q5_1, QK5_1><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>
360        (cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
361}
362
363static void ggml_cpy_q5_1_f32_cuda(
364    const char * cx, char * cdst, const int64_t ne,
365    const int64_t ne00, const int64_t ne01, const int64_t ne02,
366    const int64_t nb00, const int64_t nb01, const int64_t nb02,
367    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12,
368    const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13,
369    cudaStream_t stream) {
370    const int64_t num_blocks = (ne/QK5_1 + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
371    GGML_ASSERT(num_blocks <= INT_MAX);
372    cpy_q_f32<cpy_blck_q_f32<dequantize_q5_1, QK5_1>, QK5_1><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>(
373        cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03,
374        ne10, ne11, ne12, nb10, nb11, nb12, nb13);
375}
376
377static void ggml_cpy_f32_iq4_nl_cuda(
378    const char * cx, char * cdst, const int64_t ne,
379    const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t nb00, const int64_t nb01, const int64_t nb02,
380    const int64_t nb03, const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t nb10, const int64_t nb11, const int64_t nb12, const int64_t nb13, cudaStream_t stream) {
381
382    GGML_ASSERT(ne % QK4_NL == 0);
383    const int64_t num_blocks = (ne/QK4_NL + CUDA_CPY_BLOCK_SIZE - 1) / CUDA_CPY_BLOCK_SIZE;
384    GGML_ASSERT(num_blocks <= INT_MAX);
385    cpy_f32_q<cpy_blck_f32_iq4_nl, QK4_NL><<<num_blocks, CUDA_CPY_BLOCK_SIZE, 0, stream>>>
386        (cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13);
387}
388
389// check if a same-type copy reduces to a 2D strided copy (height rows of width
390// contiguous bytes), so it can use cudaMemcpy2DAsync instead of the scalar kernel
391static bool ggml_cuda_cpy_as_memcpy_2d(const ggml_tensor * src0, const ggml_tensor * src1,
392        size_t & width, size_t & height, size_t & spitch, size_t & dpitch) {
393    // require matching shape: a reshaped copy maps elements by flat order, which the
394    // prefix walk below does not handle
395    if (src0->type != src1->type || !ggml_are_same_shape(src0, src1)) {
396        return false;
397    }
398
399    // grow the contiguous prefix block shared by both tensors
400    size_t block_nb = ggml_element_size(src0);
401    int d = 0;
402    for (; d < GGML_MAX_DIMS; ++d) {
403        if (src0->nb[d] != block_nb || src1->nb[d] != block_nb) {
404            break;
405        }
406        block_nb *= src0->ne[d];
407    }
408
409    // d == 0: nothing contiguous; d == GGML_MAX_DIMS: fully contiguous (handled by memcpy)
410    if (d == 0 || d == GGML_MAX_DIMS) {
411        return false;
412    }
413
414    // dim d carries the rows; everything above it must be a single element
415    for (int i = d + 1; i < GGML_MAX_DIMS; ++i) {
416        if (src0->ne[i] != 1) {
417            return false;
418        }
419    }
420
421    width  = block_nb;
422    height = src0->ne[d];
423    spitch = src0->nb[d];
424    dpitch = src1->nb[d];
425
426    return spitch >= width && dpitch >= width;
427}
428
429void ggml_cuda_cpy(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, ggml_tensor * src1) {
430    const int64_t ne = ggml_nelements(src0);
431    GGML_ASSERT(ne == ggml_nelements(src1));
432
433    const int64_t ne00 = src0->ne[0];
434    const int64_t ne01 = src0->ne[1];
435    const int64_t ne02 = src0->ne[2];
436
437    //GGML_ASSERT(src0->ne[3] == 1);
438
439    const int64_t nb00 = src0->nb[0];
440    const int64_t nb01 = src0->nb[1];
441    const int64_t nb02 = src0->nb[2];
442    const int64_t nb03 = src0->nb[3];
443
444    const int64_t ne10 = src1->ne[0];
445    const int64_t ne11 = src1->ne[1];
446    const int64_t ne12 = src1->ne[2];
447
448    //GGML_ASSERT(src1->ne[3] == 1);
449
450    const int64_t nb10 = src1->nb[0];
451    const int64_t nb11 = src1->nb[1];
452    const int64_t nb12 = src1->nb[2];
453    const int64_t nb13 = src1->nb[3];
454
455    cudaStream_t main_stream = ctx.stream();
456
457    char * src0_ddc = (char *) src0->data;
458    char * src1_ddc = (char *) src1->data;
459
460    const bool contiguous_srcs = ggml_is_contiguous(src0) && ggml_is_contiguous(src1);
461    const bool can_be_transposed = nb01 == (int64_t)ggml_element_size(src0) &&
462        src0->ne[3] == 1 && nb02 == ne00 * ne01 * (int64_t)ggml_element_size(src0);
463
464    size_t mc_width = 0, mc_height = 0, mc_spitch = 0, mc_dpitch = 0;
465
466    if (src0->type == src1->type && contiguous_srcs) {
467        GGML_ASSERT(ggml_nbytes(src0) == ggml_nbytes(src1));
468#if defined(GGML_USE_MUSA) && defined(GGML_MUSA_MUDNN_COPY)
469        if (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16) {
470            CUDA_CHECK(mudnnMemcpyAsync(ctx, src1, src0));
471        } else
472#endif // GGML_USE_MUSA && GGML_MUSA_MUDNN_COPY
473        {
474            CUDA_CHECK(cudaMemcpyAsync(src1_ddc, src0_ddc, ggml_nbytes(src0), cudaMemcpyDeviceToDevice, main_stream));
475        }
476    } else if (ggml_cuda_cpy_as_memcpy_2d(src0, src1, mc_width, mc_height, mc_spitch, mc_dpitch)) {
477        CUDA_CHECK(cudaMemcpy2DAsync(src1_ddc, mc_dpitch, src0_ddc, mc_spitch,
478                                     mc_width, mc_height, cudaMemcpyDeviceToDevice, main_stream));
479    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32) {
480        if (can_be_transposed) {
481            ggml_cpy_scalar_cuda<float, float, true>
482                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
483        } else {
484            ggml_cpy_scalar_cuda<float, float>
485                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
486        }
487    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_BF16) {
488        if (contiguous_srcs) {
489            ggml_cpy_scalar_contiguous_cuda<float, nv_bfloat16>
490                (src0_ddc, src1_ddc, ne, main_stream);
491        } else {
492            ggml_cpy_scalar_cuda<float, nv_bfloat16>
493                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
494        }
495    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F16) {
496        if (contiguous_srcs) {
497            ggml_cpy_scalar_contiguous_cuda<float, half>
498                (src0_ddc, src1_ddc, ne, main_stream);
499        } else {
500            ggml_cpy_scalar_cuda<float, half>
501                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
502        }
503    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q8_0) {
504        ggml_cpy_f32_q8_0_cuda
505                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
506    } else if (src0->type == GGML_TYPE_Q8_0 && src1->type == GGML_TYPE_F32) {
507        ggml_cpy_q8_0_f32_cuda
508                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
509    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q4_0) {
510        ggml_cpy_f32_q4_0_cuda
511                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
512    } else if (src0->type == GGML_TYPE_Q4_0 && src1->type == GGML_TYPE_F32) {
513        ggml_cpy_q4_0_f32_cuda
514                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
515    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q4_1) {
516        ggml_cpy_f32_q4_1_cuda
517                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
518    } else if (src0->type == GGML_TYPE_Q4_1 && src1->type == GGML_TYPE_F32) {
519        ggml_cpy_q4_1_f32_cuda
520                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
521    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q5_0) {
522        ggml_cpy_f32_q5_0_cuda
523                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
524    } else if (src0->type == GGML_TYPE_Q5_0 && src1->type == GGML_TYPE_F32) {
525        ggml_cpy_q5_0_f32_cuda
526                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
527    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_IQ4_NL) {
528        ggml_cpy_f32_iq4_nl_cuda
529                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
530    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q5_1) {
531        ggml_cpy_f32_q5_1_cuda
532                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
533    } else if (src0->type == GGML_TYPE_Q5_1 && src1->type == GGML_TYPE_F32) {
534        ggml_cpy_q5_1_f32_cuda
535                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
536    } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F16) {
537        if (can_be_transposed) {
538            ggml_cpy_scalar_cuda<half, half, true>
539                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
540        } else {
541            ggml_cpy_scalar_cuda<half, half>
542                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
543        }
544    } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_BF16) {
545        if (contiguous_srcs) {
546            ggml_cpy_scalar_contiguous_cuda<half, nv_bfloat16>
547                (src0_ddc, src1_ddc, ne, main_stream);
548        } else {
549            ggml_cpy_scalar_cuda<half, nv_bfloat16>
550                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
551        }
552    } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F32) {
553        if (contiguous_srcs) {
554            ggml_cpy_scalar_contiguous_cuda<half, float>
555                (src0_ddc, src1_ddc, ne, main_stream);
556        } else {
557            ggml_cpy_scalar_cuda<half, float>
558                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
559        }
560    } else if (src0->type == GGML_TYPE_BF16 && src1->type == GGML_TYPE_BF16) {
561        if (can_be_transposed) {
562            ggml_cpy_scalar_cuda<nv_bfloat16, nv_bfloat16, true>
563                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
564        } else {
565            ggml_cpy_scalar_cuda<nv_bfloat16, nv_bfloat16>
566                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
567        }
568    } else if (src0->type == GGML_TYPE_BF16 && src1->type == GGML_TYPE_F16) {
569        if (contiguous_srcs) {
570            ggml_cpy_scalar_contiguous_cuda<nv_bfloat16, half>
571                (src0_ddc, src1_ddc, ne, main_stream);
572        } else {
573            ggml_cpy_scalar_cuda<nv_bfloat16, half>
574                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
575        }
576    } else if (src0->type == GGML_TYPE_BF16 && src1->type == GGML_TYPE_F32) {
577        if (contiguous_srcs) {
578            ggml_cpy_scalar_contiguous_cuda<nv_bfloat16, float>
579                (src0_ddc, src1_ddc, ne, main_stream);
580        } else {
581            ggml_cpy_scalar_cuda<nv_bfloat16, float>
582                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
583        }
584    } else if (src0->type == GGML_TYPE_I32 && src1->type == GGML_TYPE_I32) {
585        if (can_be_transposed) {
586            ggml_cpy_scalar_cuda<int32_t, int32_t, true>
587                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
588        } else {
589            ggml_cpy_scalar_cuda<int32_t, int32_t>
590                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
591        }
592    } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_I32) {
593        if (contiguous_srcs) {
594            ggml_cpy_scalar_contiguous_cuda<float, int32_t>
595                (src0_ddc, src1_ddc, ne, main_stream);
596        } else {
597            ggml_cpy_scalar_cuda<float, int32_t>
598                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
599        }
600    } else if (src0->type == GGML_TYPE_I32 && src1->type == GGML_TYPE_F32) {
601        if (contiguous_srcs) {
602            ggml_cpy_scalar_contiguous_cuda<int32_t, float>
603                (src0_ddc, src1_ddc, ne, main_stream);
604        } else {
605            ggml_cpy_scalar_cuda<int32_t, float>
606                (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
607        }
608    } else {
609        GGML_ABORT("%s: unsupported type combination (%s to %s)\n", __func__,
610                ggml_type_name(src0->type), ggml_type_name(src1->type));
611    }
612}
613
614void ggml_cuda_dup(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
615    const ggml_tensor * src0 = dst->src[0];
616    ggml_cuda_cpy(ctx, src0, dst);
617}