char-fork/llama.cpp

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

Oliver SimonsCUDA: Fix data-races when reusing SMEM in block_reduce (#26385)9bd4c09ea

char/aliceai-t5-moe
29.9 KiB698 linesraw
1#include "norm.cuh"
2#include <cstdint>
3
4template <int block_size>
5static __global__ void norm_f32(
6        const float * x, float * dst, const int ncols, const int64_t stride_row, const int64_t stride_channel,
7        const int64_t stride_sample, const float eps) {
8    const int nrows     = gridDim.x;
9    const int nchannels = gridDim.y;
10
11    const int row       = blockIdx.x;
12    const int channel   = blockIdx.y;
13    const int sample    = blockIdx.z;
14    const int tid       = threadIdx.x;
15
16    x   += sample*stride_sample + channel*stride_channel + row*stride_row;
17    dst += ((sample*nchannels + channel)*nrows + row)*ncols;
18
19    float2 mean_var = make_float2(0.0f, 0.0f);
20
21    ggml_cuda_pdl_sync();
22    for (int col = tid; col < ncols; col += block_size) {
23        const float xi = x[col];
24        mean_var.x += xi;
25        mean_var.y += xi * xi;
26    }
27
28    // sum up partial sums
29    extern __shared__ float2 s_sum2[];
30    mean_var = block_reduce<block_reduce_method::SUM, block_size>(mean_var, s_sum2);
31
32    const float mean = mean_var.x / ncols;
33    const float var = mean_var.y / ncols - mean * mean;
34    const float inv_std = rsqrtf(var + eps);
35
36    for (int col = tid; col < ncols; col += block_size) {
37        dst[col] = (x[col] - mean) * inv_std;
38    }
39}
40
41template <int block_size>
42static __global__ void group_norm_f32(const float * x, float * dst, const int group_size, const int ne_elements, const float eps) {
43    // blockIdx.x: num_groups idx
44    // threadIdx.x: block_size idx
45    const int start =     blockIdx.x*group_size + threadIdx.x;
46    const int end   = min(blockIdx.x*group_size + group_size,  ne_elements);
47
48    float tmp = 0.0f; // partial sum for thread in warp
49
50    ggml_cuda_pdl_sync();
51    for (int j = start; j < end; j += block_size) {
52        tmp += x[j];
53    }
54
55    extern __shared__ float s_sum[];
56    tmp = block_reduce<block_reduce_method::SUM, block_size>(tmp, s_sum);
57
58    const float mean = tmp / group_size;
59    tmp = 0.0f;
60
61    for (int j = start; j < end; j += block_size) {
62        const float xi = x[j] - mean;
63        dst[j] = xi;
64        tmp += xi * xi;
65    }
66
67    tmp = block_reduce<block_reduce_method::SUM, block_size>(tmp, s_sum + 32);
68
69    const float variance = tmp / group_size;
70    const float scale = rsqrtf(variance + eps);
71    for (int j = start; j < end; j += block_size) {
72        dst[j] *= scale;
73    }
74}
75
76template <int block_size, bool do_multiply = false, bool do_add = false>
77static __global__ void rms_norm_f32(const float * x,
78                                    float *       dst,
79                                    const int     ncols,
80                                    const int64_t stride_row,
81                                    const int64_t stride_channel,
82                                    const int64_t stride_sample,
83                                    const float   eps,
84                                    const float * mul                  = nullptr,
85                                    const int64_t mul_stride_row       = 0,
86                                    const int64_t mul_stride_channel   = 0,
87                                    const int64_t mul_stride_sample    = 0,
88                                    const uint3   mul_ncols_packed     = make_uint3(0, 0, 0),
89                                    const uint3   mul_nrows_packed     = make_uint3(0, 0, 0),
90                                    const uint3   mul_nchannels_packed = make_uint3(0, 0, 0),
91                                    const uint3   mul_nsamples_packed  = make_uint3(0, 0, 0),
92                                    const float * add                  = nullptr,
93                                    const int64_t add_stride_row       = 0,
94                                    const int64_t add_stride_channel   = 0,
95                                    const int64_t add_stride_sample    = 0,
96                                    const uint3   add_ncols_packed     = make_uint3(0, 0, 0),
97                                    const uint3   add_nrows_packed     = make_uint3(0, 0, 0),
98                                    const uint3   add_nchannels_packed = make_uint3(0, 0, 0),
99                                    const uint3   add_nsamples_packed  = make_uint3(0, 0, 0)) {
100    ggml_cuda_pdl_lc();
101    const int nrows     = gridDim.x;
102    const int nchannels = gridDim.y;
103
104    const int row       = blockIdx.x;
105    const int channel   = blockIdx.y;
106    const int sample    = blockIdx.z;
107    const int tid       = threadIdx.x;
108
109    static_assert(!do_add || do_multiply, "fusing add is not supported without multiplying");
110
111    x   += sample*stride_sample + channel*stride_channel + row*stride_row;
112    dst += ((sample*nchannels + channel)*nrows + row)*ncols;
113
114    if constexpr (do_multiply) {
115        const uint32_t mul_row     = fastmodulo(row, mul_nrows_packed);
116        const uint32_t mul_channel = fastmodulo(channel, mul_nchannels_packed);
117        const uint32_t mul_sample  = fastmodulo(sample, mul_nsamples_packed);
118        mul += mul_sample * mul_stride_sample + mul_channel * mul_stride_channel + mul_row * mul_stride_row;
119    }
120
121    if constexpr (do_add) {
122        const int add_row     = fastmodulo(row, add_nrows_packed);
123        const int add_channel = fastmodulo(channel, add_nchannels_packed);
124        const int add_sample  = fastmodulo(sample, add_nsamples_packed);
125        add += add_sample * add_stride_sample + add_channel * add_stride_channel + add_row * add_stride_row;
126    }
127
128    float tmp = 0.0f; // partial sum for thread in warp
129
130    ggml_cuda_pdl_sync();
131    for (int col = tid; col < ncols; col += block_size) {
132        const float xi = x[col];
133        tmp += xi * xi;
134    }
135
136    // sum up partial sums
137    extern __shared__ float s_sum[];
138    tmp = block_reduce<block_reduce_method::SUM, block_size>(tmp, s_sum);
139
140    const float mean = tmp / ncols;
141    const float scale = rsqrtf(mean + eps);
142
143    for (int col = tid; col < ncols; col += block_size) {
144        if constexpr (do_multiply && do_add) {
145            const int mul_col = fastmodulo(col, mul_ncols_packed);
146            const int add_col = fastmodulo(col, add_ncols_packed);
147            dst[col]          = scale * x[col] * mul[mul_col] + add[add_col];
148        } else if constexpr (do_multiply) {
149            const int mul_col = fastmodulo(col, mul_ncols_packed);
150            dst[col]          = scale * x[col] * mul[mul_col];
151        } else {
152            dst[col] = scale * x[col];
153        }
154    }
155}
156
157template <int block_size>
158static __global__ void rms_norm_back_f32(
159        const float * grad, const float * xf, float * dst, const int ncols, const float eps) {
160    const int row = blockIdx.x*blockDim.y + threadIdx.y;
161    const int tid = threadIdx.x;
162
163    grad += int64_t(row)*ncols;
164    xf   += int64_t(row)*ncols;
165    dst  += int64_t(row)*ncols;
166
167    float sum_xx = 0.0f; // sum for squares of x, equivalent to forward pass
168    float sum_xg = 0.0f; // sum for x * gradient, needed because RMS norm mixes inputs
169
170    ggml_cuda_pdl_sync();
171    for (int col = tid; col < ncols; col += block_size) {
172        const float xfi = xf[col];
173        sum_xx += xfi * xfi;
174        sum_xg += xfi * grad[col];
175    }
176
177    // sum up partial sums
178    sum_xx = warp_reduce_sum(sum_xx);
179    sum_xg = warp_reduce_sum(sum_xg);
180    if constexpr (block_size > WARP_SIZE) {
181        static_assert(block_size == 1024, "unexpected block_size");
182        __shared__ float s_sum_xx[32];
183        __shared__ float s_sum_xg[32];
184        const int warp_id = threadIdx.x / WARP_SIZE;
185        const int lane_id = threadIdx.x % WARP_SIZE;
186        if (lane_id == 0) {
187            s_sum_xx[warp_id] = sum_xx;
188            s_sum_xg[warp_id] = sum_xg;
189        }
190        __syncthreads();
191
192        sum_xx = s_sum_xx[lane_id];
193        sum_xx = warp_reduce_sum(sum_xx);
194
195        sum_xg = s_sum_xg[lane_id];
196        sum_xg = warp_reduce_sum(sum_xg);
197    }
198
199    const float mean_eps = sum_xx / ncols + eps;
200    const float sum_eps  = sum_xx + ncols*eps;
201
202    const float scale_grad = rsqrtf(mean_eps);
203    const float scale_x    = -scale_grad * sum_xg/sum_eps;
204
205    for (int col = tid; col < ncols; col += block_size) {
206        dst[col] = scale_grad*grad[col] + scale_x*xf[col];
207    }
208}
209
210// template <int block_size>
211// static __global__ void l2_norm_f32(const float * x, float * dst, const int ncols, const float eps) {
212//     const int row = blockIdx.x*blockDim.y + threadIdx.y;
213//     const int tid = threadIdx.x;
214
215//     float tmp = 0.0f; // partial sum for thread in warp
216
217//     for (int col = tid; col < ncols; col += block_size) {
218//         const float xi = x[row*ncols + col];
219//         tmp += xi * xi;
220//     }
221
222//     // sum up partial sums
223//     tmp = warp_reduce_sum(tmp);
224//     if (block_size > WARP_SIZE) {
225//         __shared__ float s_sum[32];
226//         int warp_id = threadIdx.x / WARP_SIZE;
227//         int lane_id = threadIdx.x % WARP_SIZE;
228//         if (lane_id == 0) {
229//             s_sum[warp_id] = tmp;
230//         }
231//         __syncthreads();
232//         tmp = s_sum[lane_id];
233//         tmp = warp_reduce_sum(tmp);
234//     }
235
236//     // from https://pytorch.org/docs/stable/generated/torch.nn.functional.normalize.html
237//     const float scale = rsqrtf(fmaxf(tmp, eps * eps));
238
239//     for (int col = tid; col < ncols; col += block_size) {
240//         dst[row*ncols + col] = scale * x[row*ncols + col];
241//     }
242// }
243
244template <int block_size>
245static __global__ void l2_norm_f32(
246        const float * x, float * dst, const int ncols, const int64_t stride_row, const int64_t stride_channel,
247        const int64_t stride_sample, const float eps) {
248    const int nrows     = gridDim.x;
249    const int nchannels = gridDim.y;
250
251    const int row       = blockIdx.x;
252    const int channel   = blockIdx.y;
253    const int sample    = blockIdx.z;
254    const int tid       = threadIdx.x;
255
256    x   += sample*stride_sample + channel*stride_channel + row*stride_row;
257    dst += ((sample*nchannels + channel)*nrows + row)*ncols;
258
259    float tmp = 0.0f; // partial sum for thread in warp
260
261    ggml_cuda_pdl_sync();
262    for (int col = tid; col < ncols; col += block_size) {
263        const float xi = x[col];
264        tmp += xi * xi;
265    }
266
267    // sum up partial sums
268    extern __shared__ float s_sum[];
269    tmp = block_reduce<block_reduce_method::SUM, block_size>(tmp, s_sum);
270    ggml_cuda_pdl_lc();
271
272    // from https://pytorch.org/docs/stable/generated/torch.nn.functional.normalize.html
273    const float scale = rsqrtf(fmaxf(tmp, eps * eps));
274
275    for (int col = tid; col < ncols; col += block_size) {
276        dst[col] = scale * x[col];
277    }
278}
279
280static void norm_f32_cuda(
281        const float * x, float * dst, const int ncols, const int nrows, const int nchannels, const int nsamples,
282        const int64_t stride_row, const int64_t stride_channel, const int64_t stride_sample, const float eps, cudaStream_t stream) {
283    const dim3 blocks_num(nrows, nchannels, nsamples);
284    if (ncols < 1024) {
285        const dim3 block_dims(WARP_SIZE, 1, 1);
286        norm_f32<WARP_SIZE><<<blocks_num, block_dims, 0, stream>>>(x, dst, ncols, stride_row, stride_channel, stride_sample, eps);
287    } else {
288        const dim3 block_dims(1024, 1, 1);
289        norm_f32<1024><<<blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float2): 0, stream>>>(x, dst, ncols, stride_row, stride_channel, stride_sample, eps);
290    }
291}
292
293static void group_norm_f32_cuda(
294        const float * x, float * dst, const int num_groups, const float eps, const int group_size, const int ne_elements, cudaStream_t stream) {
295    if (group_size < 1024) {
296        const dim3 block_dims(WARP_SIZE, 1, 1);
297        group_norm_f32<WARP_SIZE><<<num_groups, block_dims, 0, stream>>>(x, dst, group_size, ne_elements, eps);
298    } else {
299        const dim3 block_dims(1024, 1, 1);
300        group_norm_f32<1024><<<num_groups, block_dims, block_dims.x > WARP_SIZE ? 2 * 32 * sizeof(float): 0, stream>>>(x, dst, group_size, ne_elements, eps);
301    }
302}
303
304static void rms_norm_f32_cuda(
305        const float * x, float * dst, const int ncols, const int nrows, const int nchannels, const int nsamples,
306        const int64_t stride_row, const int64_t stride_channel, const int64_t stride_sample, const float eps, cudaStream_t stream) {
307    const dim3 blocks_num(nrows, nchannels, nsamples);
308    if (ncols < 1024) {
309        const dim3 block_dims(256, 1, 1);
310        const ggml_cuda_kernel_launch_params launch_params = {blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
311        ggml_cuda_kernel_launch(rms_norm_f32<256, false>, launch_params,
312            x, dst, ncols, stride_row, stride_channel, stride_sample, eps,
313        // underlying cudaLaunchKernelEx does not support default params
314        nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0),
315        nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0));
316    } else {
317        const dim3 block_dims(1024, 1, 1);
318        const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
319        ggml_cuda_kernel_launch(rms_norm_f32<1024, false>, launch_params, x, dst, ncols, stride_row, stride_channel, stride_sample, eps,
320        // underlying cudaLaunchKernelEx does not support default params
321        nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0),
322        nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0));
323    }
324}
325
326static void rms_norm_mul_f32_cuda(const float *  x,
327                                  const float *  mul,
328                                  const float *  add,
329                                  float *        dst,
330                                  const int      ncols,
331                                  const int      nrows,
332                                  const int      nchannels,
333                                  const int      nsamples,
334                                  const int64_t  stride_row,
335                                  const int64_t  stride_channel,
336                                  const int64_t  stride_sample,
337                                  const int64_t  mul_stride_row,
338                                  const int64_t  mul_stride_channel,
339                                  const int64_t  mul_stride_sample,
340                                  const uint32_t mul_ncols,
341                                  const uint32_t mul_nrows,
342                                  const uint32_t mul_nchannels,
343                                  const uint32_t mul_nsamples,
344                                  const int64_t  add_stride_row,
345                                  const int64_t  add_stride_channel,
346                                  const int64_t  add_stride_sample,
347                                  const uint32_t add_ncols,
348                                  const uint32_t add_nrows,
349                                  const uint32_t add_nchannels,
350                                  const uint32_t add_nsamples,
351                                  const float    eps,
352                                  cudaStream_t   stream) {
353    const dim3 blocks_num(nrows, nchannels, nsamples);
354    if (mul == nullptr) {
355        rms_norm_f32_cuda(x, dst, ncols, nrows, nchannels, nsamples, stride_row, stride_channel, stride_sample, eps, stream);
356        return;
357    }
358    if (add == nullptr) {
359        const uint3 mul_ncols_packed     = init_fastdiv_values(mul_ncols);
360        const uint3 mul_nrows_packed     = init_fastdiv_values(mul_nrows);
361        const uint3 mul_nchannels_packed = init_fastdiv_values(mul_nchannels);
362        const uint3 mul_nsamples_packed  = init_fastdiv_values(mul_nsamples);
363        if (ncols < 1024) {
364            const dim3 block_dims(256, 1, 1);
365            const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
366            ggml_cuda_kernel_launch(rms_norm_f32<256, true>, launch_params,
367                x, dst, ncols, stride_row, stride_channel, stride_sample, eps, mul, mul_stride_row, mul_stride_channel,
368                mul_stride_sample, mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed,
369                // underlying cudaLaunchKernelEx does not support default params
370            nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0));
371        } else {
372            const dim3 block_dims(1024, 1, 1);
373            const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
374            ggml_cuda_kernel_launch(rms_norm_f32<1024, true>, launch_params,
375                x, dst, ncols, stride_row, stride_channel, stride_sample, eps, mul, mul_stride_row, mul_stride_channel,
376                mul_stride_sample, mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed,
377                // underlying cudaLaunchKernelEx does not support default params
378            nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0));
379        }
380    } else {
381        const uint3 mul_ncols_packed     = init_fastdiv_values(mul_ncols);
382        const uint3 mul_nrows_packed     = init_fastdiv_values(mul_nrows);
383        const uint3 mul_nchannels_packed = init_fastdiv_values(mul_nchannels);
384        const uint3 mul_nsamples_packed  = init_fastdiv_values(mul_nsamples);
385
386        const uint3 add_ncols_packed     = init_fastdiv_values(add_ncols);
387        const uint3 add_nrows_packed     = init_fastdiv_values(add_nrows);
388        const uint3 add_nchannels_packed = init_fastdiv_values(add_nchannels);
389        const uint3 add_nsamples_packed  = init_fastdiv_values(add_nsamples);
390        if (ncols < 1024) {
391            const dim3 block_dims(256, 1, 1);
392            const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims,block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
393            ggml_cuda_kernel_launch(rms_norm_f32<256, true, true>, launch_params,
394                x, dst, ncols, stride_row, stride_channel, stride_sample, eps, mul, mul_stride_row, mul_stride_channel,
395                mul_stride_sample, mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed, add,
396                add_stride_row, add_stride_channel, add_stride_sample, add_ncols_packed, add_nrows_packed,
397                add_nchannels_packed, add_nsamples_packed);
398        } else {
399            const dim3 block_dims(1024, 1, 1);
400            const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
401            ggml_cuda_kernel_launch(rms_norm_f32<1024, true, true>, launch_params,
402                x, dst, ncols, stride_row, stride_channel, stride_sample, eps, mul, mul_stride_row, mul_stride_channel,
403                mul_stride_sample, mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed, add,
404                add_stride_row, add_stride_channel, add_stride_sample, add_ncols_packed, add_nrows_packed,
405                add_nchannels_packed, add_nsamples_packed);
406        }
407    }
408}
409
410static void rms_norm_back_f32_cuda(const float * grad, const float * xf, float * dst, const int ncols, const int nrows, const float eps, cudaStream_t stream) {
411    if (ncols < 1024) {
412        const dim3 block_dims(WARP_SIZE, 1, 1);
413        rms_norm_back_f32<WARP_SIZE><<<nrows, block_dims, 0, stream>>>(grad, xf, dst, ncols, eps);
414    } else {
415        const dim3 block_dims(1024, 1, 1);
416        rms_norm_back_f32<1024><<<nrows, block_dims, 0, stream>>>(grad, xf, dst, ncols, eps);
417    }
418}
419
420static void l2_norm_f32_cuda(
421        const float * x, float * dst, const int ncols, const int nrows, const int nchannels, const int nsamples,
422        const int64_t stride_row, const int64_t stride_channel, const int64_t stride_sample, const float eps, cudaStream_t stream) {
423    const dim3 blocks_num(nrows, nchannels, nsamples);
424    if (ncols < 1024) {
425        const dim3 block_dims(WARP_SIZE, 1, 1);
426        const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, 0, stream};
427        ggml_cuda_kernel_launch(l2_norm_f32<WARP_SIZE>, launch_params, x, dst, ncols, stride_row, stride_channel, stride_sample, eps);
428    } else {
429        const dim3 block_dims(1024, 1, 1);
430        const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
431        ggml_cuda_kernel_launch(l2_norm_f32<1024>, launch_params, x, dst, ncols, stride_row, stride_channel, stride_sample, eps);
432    }
433}
434
435void ggml_cuda_op_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
436    const ggml_tensor * src0 = dst->src[0];
437    const float * src0_d = (const float *) src0->data;
438    float * dst_d = (float *) dst->data;
439    cudaStream_t stream = ctx.stream();
440
441    GGML_ASSERT(src0->type == GGML_TYPE_F32);
442    GGML_ASSERT( dst->type == GGML_TYPE_F32);
443
444    GGML_TENSOR_UNARY_OP_LOCALS;
445
446    float eps;
447    memcpy(&eps, dst->op_params, sizeof(float));
448    GGML_ASSERT(eps >= 0.0f);
449
450    const size_t ts0 = ggml_type_size(src0->type);
451    GGML_ASSERT(nb00 == ts0);
452    const int64_t s01 = nb01 / ts0;
453    const int64_t s02 = nb02 / ts0;
454    const int64_t s03 = nb03 / ts0;
455
456    norm_f32_cuda(src0_d, dst_d, ne00, ne01, ne02, ne03, s01, s02, s03, eps, stream);
457}
458
459void ggml_cuda_op_group_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
460    const ggml_tensor * src0 = dst->src[0];
461    const float * src0_d = (const float *)src0->data;
462    float * dst_d = (float *)dst->data;
463    cudaStream_t stream = ctx.stream();
464
465    GGML_ASSERT(src0->type == GGML_TYPE_F32);
466    GGML_ASSERT( dst->type == GGML_TYPE_F32);
467
468    int num_groups = dst->op_params[0];
469
470    float eps;
471    memcpy(&eps, dst->op_params + 1, sizeof(float));
472    GGML_ASSERT(eps >= 0.0f);
473
474    int group_size = src0->ne[0] * src0->ne[1] * ((src0->ne[2] + num_groups - 1) / num_groups);
475    group_norm_f32_cuda(src0_d, dst_d, num_groups * src0->ne[3], eps, group_size, ggml_nelements(src0), stream);
476}
477
478void ggml_cuda_op_rms_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
479    const ggml_tensor * src0 = dst->src[0];
480    const float * src0_d = (const float *) src0->data;
481    float * dst_d = (float *) dst->data;
482    cudaStream_t stream = ctx.stream();
483
484    GGML_ASSERT(src0->type == GGML_TYPE_F32);
485    GGML_ASSERT( dst->type == GGML_TYPE_F32);
486
487    GGML_TENSOR_UNARY_OP_LOCALS;
488
489    float eps;
490    memcpy(&eps, dst->op_params, sizeof(float));
491    GGML_ASSERT(eps >= 0.0f);
492
493    const size_t ts0 = ggml_type_size(src0->type);
494    GGML_ASSERT(nb00 == ts0);
495    const int64_t s01 = nb01 / ts0;
496    const int64_t s02 = nb02 / ts0;
497    const int64_t s03 = nb03 / ts0;
498
499    rms_norm_f32_cuda(src0_d, dst_d, ne00, ne01, ne02, ne03, s01, s02, s03, eps, stream);
500}
501
502void ggml_cuda_op_rms_norm_fused(ggml_backend_cuda_context & ctx, ggml_tensor * dst, ggml_tensor * mul_tensor) {
503    const ggml_tensor * rms_norm_src = (ggml_tensor *) dst->src[0];
504    float eps = 0.0f;
505
506    memcpy(&eps, dst->op_params, sizeof(float));
507
508    const float * src0_d = (const float *) rms_norm_src->data;
509    const float * mul_d = nullptr;
510    const ggml_tensor * mul_src = nullptr;
511
512    if (mul_tensor->src[0] == dst) {
513        mul_d = (float *) mul_tensor->src[1]->data;
514        mul_src = mul_tensor->src[1];
515    } else if(mul_tensor->src[1] == dst) {
516        mul_d = (float *) mul_tensor->src[0]->data;
517        mul_src = mul_tensor->src[0];
518    } else {
519        GGML_ASSERT(false);
520    }
521
522    float * dst_d = (float *) mul_tensor->data;
523    cudaStream_t stream = ctx.stream();
524
525    GGML_ASSERT(rms_norm_src->type == GGML_TYPE_F32);
526    GGML_ASSERT(dst->type == GGML_TYPE_F32);
527    GGML_ASSERT(mul_tensor->type == GGML_TYPE_F32);
528    GGML_ASSERT(eps >= 0.0f);
529
530    const int64_t ne00 = rms_norm_src->ne[0];
531    const int64_t ne01 = rms_norm_src->ne[1];
532    const int64_t ne02 = rms_norm_src->ne[2];
533    const int64_t ne03 = rms_norm_src->ne[3];
534
535    const size_t ts0 = ggml_type_size(rms_norm_src->type);
536    GGML_ASSERT(rms_norm_src->nb[0] == ts0);
537    const int64_t s01 = rms_norm_src->nb[1] / ts0;
538    const int64_t s02 = rms_norm_src->nb[2] / ts0;
539    const int64_t s03 = rms_norm_src->nb[3] / ts0;
540
541    const size_t ts_mul = ggml_type_size(mul_src->type);
542    GGML_ASSERT(mul_src->nb[0] == ts_mul);
543    const int64_t mul_s01 = mul_src->nb[1] / ts_mul;
544    const int64_t mul_s02 = mul_src->nb[2] / ts_mul;
545    const int64_t mul_s03 = mul_src->nb[3] / ts_mul;
546
547    const int mul_ncols     = mul_src->ne[0];
548    const int mul_nrows     = mul_src->ne[1];
549    const int mul_nchannels = mul_src->ne[2];
550    const int mul_nsamples  = mul_src->ne[3];
551
552    rms_norm_mul_f32_cuda(src0_d, mul_d, nullptr, dst_d,
553                          ne00, ne01, ne02, ne03,
554                          /*s00*/ s01, s02, s03,
555                          /*mul_s00*/ mul_s01, mul_s02, mul_s03,
556                          mul_ncols, mul_nrows, mul_nchannels, mul_nsamples,
557                          /*add_s00*/ 0, 0, 0,
558                          0, 0, 0, 0,
559                          eps, stream);
560}
561
562void ggml_cuda_op_rms_norm_fused_add(ggml_backend_cuda_context & ctx,
563                                     ggml_tensor *               dst,
564                                     ggml_tensor *               mul_tensor,
565                                     ggml_tensor *               add_tensor) {
566    const ggml_tensor * rms_norm_src = (ggml_tensor *) dst->src[0];
567    float               eps          = 0.0f;
568
569    memcpy(&eps, dst->op_params, sizeof(float));
570
571    const float *       src0_d  = (const float *) rms_norm_src->data;
572    const float *       mul_d   = nullptr;
573    const ggml_tensor * mul_src = nullptr;
574
575    if (mul_tensor->src[0] == dst) {
576        mul_d   = (float *) mul_tensor->src[1]->data;
577        mul_src = mul_tensor->src[1];
578    } else if (mul_tensor->src[1] == dst) {
579        mul_d   = (float *) mul_tensor->src[0]->data;
580        mul_src = mul_tensor->src[0];
581    } else {
582        GGML_ASSERT(false);
583    }
584
585    const float *       add_d   = nullptr;
586    const ggml_tensor * add_src = nullptr;
587
588    if (add_tensor->src[0] == mul_tensor) {
589        add_d   = (float *) add_tensor->src[1]->data;
590        add_src = add_tensor->src[1];
591    } else if (add_tensor->src[1] == mul_tensor) {
592        add_d   = (float *) add_tensor->src[0]->data;
593        add_src = add_tensor->src[0];
594    } else {
595        GGML_ASSERT(false);
596    }
597
598    float *      dst_d  = (float *) add_tensor->data;
599    cudaStream_t stream = ctx.stream();
600
601    GGML_ASSERT(rms_norm_src->type == GGML_TYPE_F32);
602    GGML_ASSERT(dst->type == GGML_TYPE_F32);
603    GGML_ASSERT(mul_tensor->type == GGML_TYPE_F32);
604    GGML_ASSERT(add_tensor->type == GGML_TYPE_F32);
605    GGML_ASSERT(eps >= 0.0f);
606
607    const int64_t ne00 = rms_norm_src->ne[0];
608    const int64_t ne01 = rms_norm_src->ne[1];
609    const int64_t ne02 = rms_norm_src->ne[2];
610    const int64_t ne03 = rms_norm_src->ne[3];
611
612    const size_t ts0 = ggml_type_size(rms_norm_src->type);
613    GGML_ASSERT(rms_norm_src->nb[0] == ts0);
614    const int64_t s01 = rms_norm_src->nb[1] / ts0;
615    const int64_t s02 = rms_norm_src->nb[2] / ts0;
616    const int64_t s03 = rms_norm_src->nb[3] / ts0;
617
618    const size_t ts_mul = ggml_type_size(mul_src->type);
619    GGML_ASSERT(mul_src->nb[0] == ts_mul);
620    const int64_t mul_s01 = mul_src->nb[1] / ts_mul;
621    const int64_t mul_s02 = mul_src->nb[2] / ts_mul;
622    const int64_t mul_s03 = mul_src->nb[3] / ts_mul;
623
624    const int mul_ncols     = mul_src->ne[0];
625    const int mul_nrows     = mul_src->ne[1];
626    const int mul_nchannels = mul_src->ne[2];
627    const int mul_nsamples  = mul_src->ne[3];
628
629    const size_t ts_add = ggml_type_size(add_src->type);
630    GGML_ASSERT(add_src->nb[0] == ts_add);
631    const int64_t add_s01 = add_src->nb[1] / ts_add;
632    const int64_t add_s02 = add_src->nb[2] / ts_add;
633    const int64_t add_s03 = add_src->nb[3] / ts_add;
634
635    const int add_ncols     = add_src->ne[0];
636    const int add_nrows     = add_src->ne[1];
637    const int add_nchannels = add_src->ne[2];
638    const int add_nsamples  = add_src->ne[3];
639
640    rms_norm_mul_f32_cuda(src0_d, mul_d,add_d,dst_d,
641                          ne00,ne01, ne02, ne03,
642                          /*s00*/ s01, s02, s03,
643                          /*mul_s00*/ mul_s01, mul_s02, mul_s03,
644                          mul_ncols, mul_nrows, mul_nchannels, mul_nsamples,
645                          /*add_s00*/ add_s01, add_s02, add_s03,
646                          add_ncols, add_nrows, add_nchannels, add_nsamples,
647                          eps, stream);
648}
649
650void ggml_cuda_op_rms_norm_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
651    const ggml_tensor * grad  = dst->src[0]; // gradients
652    const ggml_tensor * src0f = dst->src[1]; // src0 from forward pass
653
654    const float * grad_d  = (const float *) grad->data;
655    const float * src0f_d = (const float *) src0f->data;
656    float       * dst_d   = (float       *) dst->data;
657
658    cudaStream_t stream = ctx.stream();
659
660    GGML_ASSERT(ggml_is_contiguous(grad));
661
662    GGML_ASSERT( grad->type == GGML_TYPE_F32);
663    GGML_ASSERT(src0f->type == GGML_TYPE_F32);
664    GGML_ASSERT(  dst->type == GGML_TYPE_F32);
665
666    const int64_t ne00 = src0f->ne[0];
667    const int64_t nrows = ggml_nrows(src0f);
668
669    float eps;
670    memcpy(&eps, dst->op_params, sizeof(float));
671    GGML_ASSERT(eps >= 0.0f);
672
673    rms_norm_back_f32_cuda(grad_d, src0f_d, dst_d, ne00, nrows, eps, stream);
674}
675
676void ggml_cuda_op_l2_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
677    const ggml_tensor * src0 = dst->src[0];
678    const float * src0_d = (const float *) src0->data;
679    float * dst_d = (float *) dst->data;
680    cudaStream_t stream = ctx.stream();
681
682    GGML_ASSERT(src0->type == GGML_TYPE_F32);
683    GGML_ASSERT( dst->type == GGML_TYPE_F32);
684
685    GGML_TENSOR_UNARY_OP_LOCALS;
686
687    float eps;
688    memcpy(&eps, dst->op_params, sizeof(float));
689    GGML_ASSERT(eps >= 0.0f);
690
691    const size_t ts0 = ggml_type_size(src0->type);
692    GGML_ASSERT(nb00 == ts0);
693    const int64_t s01 = nb01 / ts0;
694    const int64_t s02 = nb02 / ts0;
695    const int64_t s03 = nb03 / ts0;
696
697    l2_norm_f32_cuda(src0_d, dst_d, ne00, ne01, ne02, ne03, s01, s02, s03, eps, stream);
698}