ai.onnx.GroupNormalization / build /webgpu /group-normalization-splitk-apply.wgsl.jinja
Xenova's picture
Xenova HF Staff
sync 2e7068faf55e
1f79789 verified
Raw
History Blame
1.28 kB
{% if usesF16 %}
enable f16;
{% endif %}
{{ env.wgsl.resourceDeclarations }}
const HIDDEN: u32 = {{ hiddenSize }}u;
const SPATIAL: u32 = {{ spatial }}u;
const CPG: u32 = {{ channelsPerGroup }}u;
const GROUPS: u32 = {{ numGroups }}u;
const WG: u32 = {{ workgroupSize }}u;
const SPLIT: u32 = {{ split }}u;
const EPSILON: f32 = {{ epsilon }};
@compute @workgroup_size(WG, 1, 1)
fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
let row = wg.x;
let part = wg.z;
if (row >= params.rows) { return; }
var pair = vec2<f32>(0.0);
for (var p = 0u; p < SPLIT; p = p + 1u) { pair = pair + partials[row * SPLIT + p]; }
let base = row * HIDDEN;
let shift = f32(x[base]);
let mean_d = pair.x / f32(HIDDEN);
let variance = max(pair.y / f32(HIDDEN) - mean_d * mean_d, 0.0);
let mean = shift + mean_d;
let inv_std = inverseSqrt(variance + EPSILON);
let group = row % GROUPS;
let chunk = (HIDDEN + SPLIT - 1u) / SPLIT;
let start = part * chunk;
let end = min(start + chunk, HIDDEN);
for (var d = start + lid.x; d < end; d = d + WG) {
let channel = group * CPG + d / SPATIAL;
let index = base + d;
y[index] = {{ scalar }}((f32(x[index]) - mean) * inv_std * f32(scale[channel]) + f32(bias[channel]));
}
}