oarust 0.8.6

GPU-first semantic computing engine written in Rust
// Deterministic reductions for the MIMO adjoint: head-to-group Q/K gradients,
// shared angle gradients, and batch partials for all learned parameters.

import storage;
import attributes;

struct PushConstants {
	uint dc_head_idx, db_head_idx, dangle_head_idx;
	uint dc_bias_batch_idx, db_bias_batch_idx, dd_batch_idx;
	uint dmx_batch_idx, dmz_batch_idx, dmo_batch_idx, dnorm_batch_idx;
	uint dc_idx, db_idx, dangle_idx, dc_bias_idx, db_bias_idx, dd_idx;
	uint dmx_idx, dmz_idx, dmo_idx, dnorm_idx;
	uint b, l, h, g, p, n, a, r, count;
};
[[vk::push_constant]] PushConstants push;
[[vk::binding(0, 0)]] RWByteAddressBuffer storage_buffers[];

[kernel_name("mamba3_mimo_backward_reduce")]
[domain("ml")]
[variant("reduce")]
[dtype("f32")]
[status("experimental")]
[shader("compute")]
[numthreads(256, 1, 1)]
void main(uint3 dispatchId : SV_DispatchThreadID) {
	uint index = dispatchId.x;
	if (index >= push.count) return;
	uint groupCount = push.b * push.l * push.r * push.g * push.n;
	uint angleCount = push.b * push.l * push.a;
	uint biasCount = push.h * push.r * push.n;
	uint mimoCount = push.h * push.r * push.p;
	uint normCount = push.h * push.p;
	uint cursor = 0u;
	if (index < groupCount) {
		uint n = index % push.n;
		uint q = index / push.n;
		uint rg = q % (push.r * push.g);
		uint token = q / (push.r * push.g);
		uint r = rg / push.g;
		uint g = rg % push.g;
		uint headsPerGroup = push.h / push.g;
		float dc = 0.0f, db = 0.0f;
		for (uint local = 0u; local < headsPerGroup; ++local) {
			uint h = g * headsPerGroup + local;
			uint headIndex = ((token * push.h + h) * push.r + r) * push.n + n;
			dc += load_f32(storage_buffers[push.dc_head_idx], headIndex);
			db += load_f32(storage_buffers[push.db_head_idx], headIndex);
		}
		store_f32(storage_buffers[push.dc_idx], index, dc);
		store_f32(storage_buffers[push.db_idx], index, db);
		return;
	}
	cursor += groupCount;
	if (index < cursor + angleCount) {
		uint localIndex = index - cursor;
		uint a = localIndex % push.a;
		uint token = localIndex / push.a;
		uint t = token % push.l;
		uint b = token / push.l;
		float value = 0.0f;
		for (uint h = 0u; h < push.h; ++h)
			value += load_f32(storage_buffers[push.dangle_head_idx], ((b * push.h + h) * push.l + t) * push.a + a);
		store_f32(storage_buffers[push.dangle_idx], localIndex, value);
		return;
	}
	cursor += angleCount;
	if (index < cursor + biasCount) {
		uint localIndex = index - cursor;
		float dc = 0.0f, db = 0.0f;
		for (uint b = 0u; b < push.b; ++b) {
			uint partial = b * biasCount + localIndex;
			dc += load_f32(storage_buffers[push.dc_bias_batch_idx], partial);
			db += load_f32(storage_buffers[push.db_bias_batch_idx], partial);
		}
		store_f32(storage_buffers[push.dc_bias_idx], localIndex, dc);
		store_f32(storage_buffers[push.db_bias_idx], localIndex, db);
		return;
	}
	cursor += biasCount;
	if (index < cursor + push.h) {
		uint h = index - cursor;
		float value = 0.0f;
		for (uint b = 0u; b < push.b; ++b)
			value += load_f32(storage_buffers[push.dd_batch_idx], b * push.h + h);
		store_f32(storage_buffers[push.dd_idx], h, value);
		return;
	}
	cursor += push.h;
	if (index < cursor + mimoCount) {
		uint localIndex = index - cursor;
		float dx = 0.0f, dz = 0.0f, dout = 0.0f;
		for (uint b = 0u; b < push.b; ++b) {
			uint partial = b * mimoCount + localIndex;
			dx += load_f32(storage_buffers[push.dmx_batch_idx], partial);
			dz += load_f32(storage_buffers[push.dmz_batch_idx], partial);
			dout += load_f32(storage_buffers[push.dmo_batch_idx], partial);
		}
		store_f32(storage_buffers[push.dmx_idx], localIndex, dx);
		store_f32(storage_buffers[push.dmz_idx], localIndex, dz);
		store_f32(storage_buffers[push.dmo_idx], localIndex, dout);
		return;
	}
	cursor += mimoCount;
	uint normIndex = index - cursor;
	if (normIndex < normCount) {
		float value = 0.0f;
		for (uint b = 0u; b < push.b; ++b)
			value += load_f32(storage_buffers[push.dnorm_batch_idx], b * normCount + normIndex);
		store_f32(storage_buffers[push.dnorm_idx], normIndex, value);
	}
}