Files
armorpaint/base/tools/iris/iris_vulkan_qwen_rmsnorm.comp
T
2026-06-17 23:36:47 +02:00

46 lines
1.4 KiB
Plaintext

#version 450
/*
* Qwen3 RMSNorm: per-row normalization over `hidden`, scaled by a bf16 weight.
* out[s,i] = x[s,i] / sqrt(mean(x[s,:]^2) + eps) * weight[i]
* One workgroup per row; the row's elements are reduced in shared memory.
* Activations (in/out) are f32; the weight is bf16 (packed two-per-uint).
*/
layout(local_size_x = 256) in;
layout(std430, binding = 0) readonly buffer In { float x[]; };
layout(std430, binding = 1) readonly buffer W { uint wbf[]; };
layout(std430, binding = 2) writeonly buffer Out { float outp[]; };
layout(push_constant) uniform PC { uint rows, hidden; float eps; } pc;
float load_bf16(uint e) {
uint w = wbf[e >> 1u];
uint h = ((e & 1u) == 0u) ? (w & 0xffffu) : (w >> 16u);
return uintBitsToFloat(h << 16u);
}
shared float s_sq[256];
void main() {
uint row = gl_WorkGroupID.x;
uint tid = gl_LocalInvocationID.x;
uint base = row * pc.hidden;
float sq = 0.0;
for (uint i = tid; i < pc.hidden; i += 256u) {
float v = x[base + i];
sq += v * v;
}
s_sq[tid] = sq;
barrier();
for (uint s = 128u; s > 0u; s >>= 1u) {
if (tid < s) s_sq[tid] += s_sq[tid + s];
barrier();
}
float inv = inversesqrt(s_sq[0] / float(pc.hidden) + pc.eps);
for (uint i = tid; i < pc.hidden; i += 256u) {
outp[base + i] = x[base + i] * inv * load_bf16(i);
}
}