#include #include #include "../common.cuh" __global__ void depthwise_causal_conv1d_silu_bf16_kernel( const __nv_bfloat16* __restrict__ x, const __nv_bfloat16* __restrict__ w, __nv_bfloat16* __restrict__ out, int seq_len, int channels, int kernel ) { int idx = blockIdx.x * blockDim.x + threadIdx.x; int total = seq_len * channels; if (idx >= total) return; int c = idx % channels; int t = idx / channels; float acc = 0.0f; for (int k = 0; k < kernel; ++k) { int src_t = t - (kernel - 1 - k); if (src_t >= 0) { float xv = __bfloat162float(x[src_t * channels + c]); float wv = __bfloat162float(w[c * kernel + k]); acc += xv * wv; } } float y = acc / (1.0f + expf(-acc)); out[idx] = __float2bfloat16(y); } __global__ void deltanet_ar_bf16_kernel( const __nv_bfloat16* __restrict__ q, const __nv_bfloat16* __restrict__ k, const __nv_bfloat16* __restrict__ v, const __nv_bfloat16* __restrict__ beta, const __nv_bfloat16* __restrict__ alpha_softplus, const __nv_bfloat16* __restrict__ a_log, __nv_bfloat16* __restrict__ state, __nv_bfloat16* __restrict__ out, int key_heads, int value_heads, int head_dim ) { int idx = blockIdx.x * blockDim.x + threadIdx.x; int total = value_heads * head_dim; if (idx >= total) return; int h = idx / head_dim; int j = idx % head_dim; int key_h = h * key_heads / value_heads; float beta_h = __bfloat162float(beta[h]); float gate = expf(__bfloat162float(alpha_softplus[h]) * __bfloat162float(a_log[h])); float sk = 0.0f; for (int i = 0; i < head_dim; ++i) { float s = __bfloat162float(state[(h * head_dim + i) * head_dim + j]); float ki = __bfloat162float(k[key_h * head_dim + i]); s *= gate; state[(h * head_dim + i) * head_dim + j] = __float2bfloat16(s); sk += s * ki; } float vj = __bfloat162float(v[h * head_dim + j]); float d = (vj - sk) * beta_h; float out_j = 0.0f; for (int i = 0; i < head_dim; ++i) { float ki = __bfloat162float(k[key_h * head_dim + i]); float qi = __bfloat162float(q[key_h * head_dim + i]) / sqrtf((float)head_dim); int sidx = (h * head_dim + i) * head_dim + j; float s = __bfloat162float(state[sidx]) + ki * d; state[sidx] = __float2bfloat16(s); out_j += s * qi; } out[h * head_dim + j] = __float2bfloat16(out_j); } // Stateful depthwise causal convolution for hybrid recurrent attention. // `state` stores the preceding `kernel - 1` inputs in chronological order. // One thread owns a channel, so the state update is race-free for any seq_len. __global__ void depthwise_causal_conv1d_stateful_silu_bf16_kernel( const __nv_bfloat16* __restrict__ x, const __nv_bfloat16* __restrict__ w, __nv_bfloat16* __restrict__ state, __nv_bfloat16* __restrict__ out, int seq_len, int channels, int kernel ) { int c = blockIdx.x * blockDim.x + threadIdx.x; if (c >= channels) return; const int history = kernel - 1; for (int t = 0; t < seq_len; ++t) { float acc = 0.0f; for (int k = 0; k < kernel; ++k) { int src_t = t - history + k; float xv; if (src_t < 0) { xv = __bfloat162float(state[c * history + history + src_t]); } else { xv = __bfloat162float(x[(long long)src_t * channels + c]); } acc += xv * __bfloat162float(w[c * kernel + k]); } out[(long long)t * channels + c] = __float2bfloat16(acc / (1.0f + expf(-acc))); } // Keep the last `history` raw projection values for the next call. for (int h = 0; h < history; ++h) { int src_t = seq_len - history + h; __nv_bfloat16 value; if (src_t < 0) { value = state[c * history + history + src_t]; } else { value = x[(long long)src_t * channels + c]; } state[c * history + h] = value; } } // L2-normalize each row using FP32 accumulation. Qwen3.5/3.6 applies this to // convolved Q and K before the delta rule (this is not RMSNorm). __global__ void l2_normalize_rows_bf16_kernel( const __nv_bfloat16* __restrict__ x, __nv_bfloat16* __restrict__ out, int rows, int cols, float eps ) { int row = blockIdx.x; if (row >= rows) return; float local = 0.0f; for (int i = threadIdx.x; i < cols; i += blockDim.x) { float v = __bfloat162float(x[(long long)row * cols + i]); local += v * v; } __shared__ float sums[256]; sums[threadIdx.x] = local; __syncthreads(); for (int stride = blockDim.x / 2; stride > 0; stride >>= 1) { if (threadIdx.x < stride) sums[threadIdx.x] += sums[threadIdx.x + stride]; __syncthreads(); } // Match torch.nn.functional.normalize / llama.cpp: clamp the norm by eps, // rather than adding eps to every non-zero norm. float inv = rsqrtf(fmaxf(sums[0], eps * eps)); for (int i = threadIdx.x; i < cols; i += blockDim.x) { out[(long long)row * cols + i] = __float2bfloat16(__bfloat162float(x[(long long)row * cols + i]) * inv); } } // Recurrent Gated DeltaNet over one or more tokens. HF stores V heads grouped // by K head, so V head h uses K/Q head floor(h / (value_heads/key_heads)). // The recurrent matrix is FP32 as required by `mamba_ssm_dtype=float32`. __global__ void deltanet_recurrent_bf16_f32_kernel( const __nv_bfloat16* __restrict__ q, const __nv_bfloat16* __restrict__ k, const __nv_bfloat16* __restrict__ v, const __nv_bfloat16* __restrict__ beta, const __nv_bfloat16* __restrict__ alpha_softplus, const __nv_bfloat16* __restrict__ a_log, float* __restrict__ state, __nv_bfloat16* __restrict__ out, int seq_len, int key_heads, int value_heads, int head_dim ) { int idx = blockIdx.x * blockDim.x + threadIdx.x; int total = value_heads * head_dim; if (idx >= total) return; int h = idx / head_dim; int j = idx % head_dim; int key_h = h * key_heads / value_heads; float a = __bfloat162float(a_log[h]); float neg_a = -expf(a); float q_scale = rsqrtf((float)head_dim); for (int t = 0; t < seq_len; ++t) { const __nv_bfloat16* q_t = q + ((long long)t * key_heads + key_h) * head_dim; const __nv_bfloat16* k_t = k + ((long long)t * key_heads + key_h) * head_dim; const __nv_bfloat16* v_t = v + ((long long)t * value_heads + h) * head_dim; float b = __bfloat162float(beta[(long long)t * value_heads + h]); float alpha = __bfloat162float(alpha_softplus[(long long)t * value_heads + h]); float decay = expf(neg_a * alpha); float sk = 0.0f; for (int i = 0; i < head_dim; ++i) { long long sidx = ((long long)h * head_dim + i) * head_dim + j; float s = state[sidx] * decay; state[sidx] = s; sk += s * __bfloat162float(k_t[i]); } float d = (__bfloat162float(v_t[j]) - sk) * b; float out_j = 0.0f; for (int i = 0; i < head_dim; ++i) { long long sidx = ((long long)h * head_dim + i) * head_dim + j; float s = state[sidx] + __bfloat162float(k_t[i]) * d; state[sidx] = s; out_j += s * (__bfloat162float(q_t[i]) * q_scale); } out[((long long)t * value_heads + h) * head_dim + j] = __float2bfloat16(out_j); } } extern "C" { void launch_depthwise_causal_conv1d_silu_bf16( const void* x, const void* w, void* out, int seq_len, int channels, int kernel, void* stream ) { int total = seq_len * channels; int block = 256; int grid = (total + block - 1) / block; depthwise_causal_conv1d_silu_bf16_kernel<<>>( (const __nv_bfloat16*)x, (const __nv_bfloat16*)w, (__nv_bfloat16*)out, seq_len, channels, kernel ); CUDA_CHECK_LAST_ERROR(); } void launch_deltanet_ar_bf16( const void* q, const void* k, const void* v, const void* beta, const void* alpha_softplus, const void* a_log, void* state, void* out, int key_heads, int value_heads, int head_dim, void* stream ) { int total = value_heads * head_dim; int block = 128; int grid = (total + block - 1) / block; deltanet_ar_bf16_kernel<<>>( (const __nv_bfloat16*)q, (const __nv_bfloat16*)k, (const __nv_bfloat16*)v, (const __nv_bfloat16*)beta, (const __nv_bfloat16*)alpha_softplus, (const __nv_bfloat16*)a_log, (__nv_bfloat16*)state, (__nv_bfloat16*)out, key_heads, value_heads, head_dim ); CUDA_CHECK_LAST_ERROR(); } void launch_depthwise_causal_conv1d_stateful_silu_bf16( const void* x, const void* w, void* state, void* out, int seq_len, int channels, int kernel, void* stream ) { int block = 256; int grid = (channels + block - 1) / block; depthwise_causal_conv1d_stateful_silu_bf16_kernel<<>>( (const __nv_bfloat16*)x, (const __nv_bfloat16*)w, (__nv_bfloat16*)state, (__nv_bfloat16*)out, seq_len, channels, kernel ); CUDA_CHECK_LAST_ERROR(); } void launch_l2_normalize_rows_bf16( const void* x, void* out, int rows, int cols, float eps, void* stream ) { l2_normalize_rows_bf16_kernel<<>>( (const __nv_bfloat16*)x, (__nv_bfloat16*)out, rows, cols, eps ); CUDA_CHECK_LAST_ERROR(); } void launch_deltanet_recurrent_bf16_f32( const void* q, const void* k, const void* v, const void* beta, const void* alpha_softplus, const void* a_log, void* state, void* out, int seq_len, int key_heads, int value_heads, int head_dim, void* stream ) { int total = value_heads * head_dim; int block = 128; int grid = (total + block - 1) / block; deltanet_recurrent_bf16_f32_kernel<<>>( (const __nv_bfloat16*)q, (const __nv_bfloat16*)k, (const __nv_bfloat16*)v, (const __nv_bfloat16*)beta, (const __nv_bfloat16*)alpha_softplus, (const __nv_bfloat16*)a_log, (float*)state, (__nv_bfloat16*)out, seq_len, key_heads, value_heads, head_dim ); CUDA_CHECK_LAST_ERROR(); } }