oarust 0.8.6

GPU-first semantic computing engine written in Rust
// Row-cooperative FP32 gradient of mean cross-entropy.

import storage;
import attributes;

struct PushConstants {
	uint logits_index;
	uint targets_index;
	uint logits_gradient_index;
	uint rows;
	uint classes;
	uint target_dtype;
};

[[vk::push_constant]] PushConstants push;
[[vk::binding(0, 0)]] RWByteAddressBuffer storage_buffers[];

groupshared float partial[256];
groupshared float row_maximum;
static const uint PORTABLE_DISPATCH_WIDTH = 65535u;

[kernel_name("cross_entropy_backward")]
[domain("ml")]
[variant("generic")]
[dtype("f32")]
[status("experimental")]
[shader("compute")]
[numthreads(256, 1, 1)]
void main(uint3 group_id : SV_GroupID, uint3 group_thread_id : SV_GroupThreadID) {
	uint row = group_id.x + group_id.y * PORTABLE_DISPATCH_WIDTH;
	uint lane = group_thread_id.x;
	if (row >= push.rows) {
		return;
	}
	uint base = row * push.classes;
	uint target = storage_buffers[push.targets_index].Load(row * 4u);

	float local_maximum = -3.402823466e+38f;
	for (uint column = lane; column < push.classes; column += 256u) {
		local_maximum = max(
			local_maximum,
			load_f32(storage_buffers[push.logits_index], base + column)
		);
	}
	partial[lane] = local_maximum;
	GroupMemoryBarrierWithGroupSync();
	for (uint stride = 128u; stride > 0u; stride >>= 1u) {
		if (lane < stride) {
			partial[lane] = max(partial[lane], partial[lane + stride]);
		}
		GroupMemoryBarrierWithGroupSync();
	}
	if (lane == 0u) {
		row_maximum = partial[0];
	}
	GroupMemoryBarrierWithGroupSync();

	float local_sum = 0.0f;
	for (uint column = lane; column < push.classes; column += 256u) {
		local_sum += exp(
			load_f32(storage_buffers[push.logits_index], base + column) - row_maximum
		);
	}
	partial[lane] = local_sum;
	GroupMemoryBarrierWithGroupSync();
	for (uint stride = 128u; stride > 0u; stride >>= 1u) {
		if (lane < stride) {
			partial[lane] += partial[lane + stride];
		}
		GroupMemoryBarrierWithGroupSync();
	}

	float inverse_sum = 1.0f / partial[0];
	float inverse_rows = 1.0f / float(push.rows);
	for (uint column = lane; column < push.classes; column += 256u) {
		uint index = base + column;
		float gradient = 0.0f / 0.0f;
		if (push.target_dtype == 1u && target < push.classes) {
			gradient = (exp(
				load_f32(storage_buffers[push.logits_index], index) - row_maximum
			) * inverse_sum - (column == target ? 1.0f : 0.0f)) * inverse_rows;
		}
		store_f32(storage_buffers[push.logits_gradient_index], index, gradient);
	}
}