llama-cpp-sys-4 0.9.0

Low Level Bindings to llama.cpp
Documentation
enable f16;

struct MulMatIdGatherParams {
    offset_ids: u32,

    n_expert: u32,
    n_expert_used: u32,
    n_tokens: u32,

    stride_ids_1: u32,
};

@group(0) @binding(0) var<storage, read_write> ids: array<i32>;        // [n_expert_used, n_tokens]
@group(0) @binding(1) var<storage, read_write> ids_slot_pos: array<u32>; // [n_expert_used * n_tokens]
@group(0) @binding(2) var<storage, read_write> ids_tiles: array<u32>; // [n_tiles, (expert, first slot, n slots) * n_tiles]

@group(0) @binding(3) var<uniform> params: MulMatIdGatherParams;

// per expert: the slot count, replaced by the first slot of the expert in ids_slot_pos by the prefix sum, then advanced as its write cursor
var<workgroup> ids_count: array<atomic<u32>, N_EXPERT>;

// launched as a single workgroup, where the threads process the elements of ids in parallel with atomics
@compute @workgroup_size(WG_SIZE)
fn main(@builtin(local_invocation_id) local_id: vec3<u32>) {

    let thread_id = local_id.x;
    let ids_slots_num = params.n_expert_used * params.n_tokens;

    for (var e = thread_id; e < N_EXPERT; e += WG_SIZE) {
        atomicStore(&ids_count[e], 0u);
    }

    workgroupBarrier();

    // count the slots of each expert
    for (var i = thread_id; i < ids_slots_num; i += WG_SIZE) {
        let row = i / params.n_expert_used;
        let col = i % params.n_expert_used;
        let expert = u32(ids[params.offset_ids + row * params.stride_ids_1 + col]);
        atomicAdd(&ids_count[expert], 1u);
    }

    workgroupBarrier();

    // exclusive prefix sum over the counts, and emit one tile descriptor per `TILE_N_SLOTS` slots of each expert
    if (thread_id == 0u) {
        var base: u32 = 0;
        var tile: u32 = 0;

        for (var e: u32 = 0; e < N_EXPERT; e += 1) {
            let n = atomicLoad(&ids_count[e]);

            atomicStore(&ids_count[e], base);

            for (var k: u32 = 0; k < n; k += TILE_N_SLOTS) {
                ids_tiles[1 + 3 * tile]     = e;
                ids_tiles[1 + 3 * tile + 1] = base + k;
                ids_tiles[1 + 3 * tile + 2] = min(n - k, TILE_N_SLOTS);
                tile += 1;
            }

            base += n;
        }

        ids_tiles[0] = tile;
    }

    workgroupBarrier();

    // store the position in ids tensor to ids_slot_pos
    for (var i = thread_id; i < ids_slots_num; i += WG_SIZE) {
        let row = i / params.n_expert_used;
        let col = i % params.n_expert_used;
        let expert = u32(ids[params.offset_ids + row * params.stride_ids_1 + col]);
        let pos = atomicAdd(&ids_count[expert], 1u);
        ids_slot_pos[pos] = i;
    }
}