makepad/libs/ai/cuda/kernels/llm/fattn/norm.cuh
Admin 7f59912916 libs/ai: one AI stack, replacing libs/ggml, llama, mlx, cuda, tts, voice2 and pbr_paint
The model code was spread across eight crates that had grown into each other:
ggml and cuda and mlx each owned part of a tensor runtime, llama and tts and
voice2 each owned part of a model, and libs/diffusion owned everything else.
They are now one tree with an explicit shape:

  libs/ai/cuda     — kernels and launch surface
  libs/ai/metal    — Metal shaders and the shim
  libs/ai/llm      — the language-model runtime (sessions, lanes, contexts,
                     the CUDA and Metal executors, the compiled Metal path)
  libs/ai/models/  — common, flux, h3, music, paint, speech, stems, vision

libs/diffusion is not deleted but demoted: what remains is the VALIDATOR
crate — several dozen `*_validate.rs` oracles that check a native
implementation against a reference, which is where they belong now that the
implementations live next door.

The functional work inside the move is mostly in the LLM runtime: N lanes that
draft while one verify batch serves all of them, per-slot prefill over a shared
folded attention arena, speculation that survives batching, and a scheduler
that reports rather than publishes. And in the CUDA build: a machine without
usable CUDA must still LINK (and say so), the default kernel arch is the
building machine's GPU, `NO_CUDA` forces the stub even where the toolkit
exists, and kernels compile in parallel with progress.

libs/video_flow is new here: classical optical flow estimation and the `mkfl`
motion-field payload — a flow field measured from a clip without a model,
which is what drives free-rate bounce-looping playback and the uprez/tween
enhance pipe.
2026-08-23 01:34:35 +02:00

188 lines
8.4 KiB
Text

// SPDX-License-Identifier: MIT
// Copyright (c) 2023-2026 The ggml authors
//
// Substantial portions derived from ggml / llama.cpp
// (https://github.com/ggml-org/llama.cpp), MIT licensed.
// The original copyright notice and permission notice are retained.
// See libs/ai/NOTICE and, where present, LICENSE in this directory.
//
#pragma once
// Official llama.cpp ggml-cuda/norm.cu rms_norm_f32 fused with MUL (+ ADD).
// Source: /Users/admin/llama.cpp/ggml/src/ggml-cuda/norm.cu:74-384
// Dispatch: ggml-cuda.cu:3994-4004 ggml_cuda_op_rms_norm_fused[_add].
#include "common.cuh"
template <int block_size, bool do_multiply, bool do_add>
static __global__ void rms_norm_f32(
const float * x,
float * dst,
const int ncols,
const int64_t stride_row,
const int64_t stride_channel,
const int64_t stride_sample,
const float eps,
const int64_t dst_stride_row,
const int64_t dst_stride_channel,
const int64_t dst_stride_sample,
const float * mul,
const int64_t mul_stride_row,
const int64_t mul_stride_channel,
const int64_t mul_stride_sample,
const uint3 mul_ncols_packed,
const uint3 mul_nrows_packed,
const uint3 mul_nchannels_packed,
const uint3 mul_nsamples_packed,
const float * add,
const int64_t add_stride_row,
const int64_t add_stride_channel,
const int64_t add_stride_sample,
const uint3 add_ncols_packed,
const uint3 add_nrows_packed,
const uint3 add_nchannels_packed,
const uint3 add_nsamples_packed) {
const int nrows = gridDim.x;
const int nchannels = gridDim.y;
const int row = blockIdx.x;
const int channel = blockIdx.y;
const int sample = blockIdx.z;
const int tid = threadIdx.x;
static_assert(!do_add || do_multiply, "fusing add is not supported without multiplying");
x += sample*stride_sample + channel*stride_channel + row*stride_row;
dst += sample*dst_stride_sample + channel*dst_stride_channel + row*dst_stride_row;
(void) nrows;
(void) nchannels;
if constexpr (do_multiply) {
const uint32_t mul_row = fastmodulo((uint32_t) row, mul_nrows_packed);
const uint32_t mul_channel = fastmodulo((uint32_t) channel, mul_nchannels_packed);
const uint32_t mul_sample = fastmodulo((uint32_t) sample, mul_nsamples_packed);
mul += (int64_t) mul_sample * mul_stride_sample
+ (int64_t) mul_channel * mul_stride_channel
+ (int64_t) mul_row * mul_stride_row;
}
if constexpr (do_add) {
const int add_row = (int) fastmodulo((uint32_t) row, add_nrows_packed);
const int add_channel = (int) fastmodulo((uint32_t) channel, add_nchannels_packed);
const int add_sample = (int) fastmodulo((uint32_t) sample, add_nsamples_packed);
add += (int64_t) add_sample * add_stride_sample
+ (int64_t) add_channel * add_stride_channel
+ (int64_t) add_row * add_stride_row;
}
float tmp = 0.0f;
for (int col = tid; col < ncols; col += block_size) {
const float xi = x[col];
tmp += xi * xi;
}
extern __shared__ float s_sum[];
tmp = block_reduce_sum<block_size>(tmp, s_sum);
const float mean = tmp / ncols;
const float scale = rsqrtf(mean + eps);
for (int col = tid; col < ncols; col += block_size) {
if constexpr (do_multiply && do_add) {
const int mul_col = (int) fastmodulo((uint32_t) col, mul_ncols_packed);
const int add_col = (int) fastmodulo((uint32_t) col, add_ncols_packed);
dst[col] = scale * x[col] * mul[mul_col] + add[add_col];
} else if constexpr (do_multiply) {
const int mul_col = (int) fastmodulo((uint32_t) col, mul_ncols_packed);
dst[col] = scale * x[col] * mul[mul_col];
} else {
dst[col] = scale * x[col];
}
}
}
static void rms_norm_mul_f32_cuda(
const float * x,
const float * mul,
const float * add,
float * dst,
const int ncols,
const int nrows,
const int nchannels,
const int nsamples,
const int64_t stride_row,
const int64_t stride_channel,
const int64_t stride_sample,
const int64_t dst_stride_row,
const int64_t dst_stride_channel,
const int64_t dst_stride_sample,
const int64_t mul_stride_row,
const int64_t mul_stride_channel,
const int64_t mul_stride_sample,
const uint32_t mul_ncols,
const uint32_t mul_nrows,
const uint32_t mul_nchannels,
const uint32_t mul_nsamples,
const int64_t add_stride_row,
const int64_t add_stride_channel,
const int64_t add_stride_sample,
const uint32_t add_ncols,
const uint32_t add_nrows,
const uint32_t add_nchannels,
const uint32_t add_nsamples,
const float eps,
cudaStream_t stream) {
const dim3 blocks_num((unsigned) nrows, (unsigned) nchannels, (unsigned) nsamples);
const uint3 mul_ncols_packed = init_fastdiv_values(mul_ncols);
const uint3 mul_nrows_packed = init_fastdiv_values(mul_nrows);
const uint3 mul_nchannels_packed = init_fastdiv_values(mul_nchannels);
const uint3 mul_nsamples_packed = init_fastdiv_values(mul_nsamples);
// llama.cpp norm.cu:342-367: do not pack add fastdiv when add is null
// (init_fastdiv_values(0) is integer divide-by-zero).
if (add == nullptr) {
if (ncols < 1024) {
const dim3 block_dims(256, 1, 1);
rms_norm_f32<256, true, false><<<blocks_num, block_dims, 32 * sizeof(float), stream>>>(
x, dst, ncols, stride_row, stride_channel, stride_sample, eps,
dst_stride_row, dst_stride_channel, dst_stride_sample,
mul, mul_stride_row, mul_stride_channel, mul_stride_sample,
mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed,
nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0),
make_uint3(0, 0, 0), make_uint3(0, 0, 0));
} else {
const dim3 block_dims(1024, 1, 1);
rms_norm_f32<1024, true, false><<<blocks_num, block_dims, 32 * sizeof(float), stream>>>(
x, dst, ncols, stride_row, stride_channel, stride_sample, eps,
dst_stride_row, dst_stride_channel, dst_stride_sample,
mul, mul_stride_row, mul_stride_channel, mul_stride_sample,
mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed,
nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0),
make_uint3(0, 0, 0), make_uint3(0, 0, 0));
}
} else {
const uint3 add_ncols_packed = init_fastdiv_values(add_ncols);
const uint3 add_nrows_packed = init_fastdiv_values(add_nrows);
const uint3 add_nchannels_packed = init_fastdiv_values(add_nchannels);
const uint3 add_nsamples_packed = init_fastdiv_values(add_nsamples);
if (ncols < 1024) {
const dim3 block_dims(256, 1, 1);
rms_norm_f32<256, true, true><<<blocks_num, block_dims, 32 * sizeof(float), stream>>>(
x, dst, ncols, stride_row, stride_channel, stride_sample, eps,
dst_stride_row, dst_stride_channel, dst_stride_sample,
mul, mul_stride_row, mul_stride_channel, mul_stride_sample,
mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed,
add, add_stride_row, add_stride_channel, add_stride_sample,
add_ncols_packed, add_nrows_packed, add_nchannels_packed, add_nsamples_packed);
} else {
const dim3 block_dims(1024, 1, 1);
rms_norm_f32<1024, true, true><<<blocks_num, block_dims, 32 * sizeof(float), stream>>>(
x, dst, ncols, stride_row, stride_channel, stride_sample, eps,
dst_stride_row, dst_stride_channel, dst_stride_sample,
mul, mul_stride_row, mul_stride_channel, mul_stride_sample,
mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed,
add, add_stride_row, add_stride_channel, add_stride_sample,
add_ncols_packed, add_nrows_packed, add_nchannels_packed, add_nsamples_packed);
}
}
}