wgml 0.2.0

Cross-platform GPU LLM inference.
Documentation
// This was mostly ported from ggml-cuda/unary.cu
// (MIT license).

#import wgblas::shape as Shape;

@group(0) @binding(0)
var<uniform> shape_dst: Shape::Shape;
@group(0) @binding(1)
var<uniform> shape_src: Shape::Shape;
@group(0) @binding(2)
var<storage, read_write> dst: array<f32>;
@group(0) @binding(3)
var<storage, read_write> src: array<f32>;
@group(0) @binding(4)
var<uniform> args: vec4<f32>;

const GELU_COEF_A: f32 = 0.044715f;
const SQRT_2_OVER_PI: f32 = 0.79788456080286535587989211986876f;
const GELU_QUICK_COEF: f32 = -1.702f;

fn abs_f32(x: f32) -> f32 {
    return abs(x);
}

fn sgn_f32(x: f32) -> f32 {
    return sign(x);
}

fn neg_f32(x: f32) -> f32 {
    return -x;
}

fn step_f32(x: f32) -> f32 {
    if x > 0.0 {
        return 1.0;
    } else {
        return 0.0;
    }
}

fn elu_f32(x: f32) -> f32 {
    if x > 0.0 {
        return x;
    } else {
        return exp(x) - 1.0;
    }
}

fn gelu_f32(x: f32) -> f32 {
    return 0.5f * x * (1.0f + tanh(SQRT_2_OVER_PI * x * (1.0f + GELU_COEF_A * x * x)));
}

fn gelu_quick_f32(x: f32) -> f32 {
    return x * (1.0f / (1.0f + exp(GELU_QUICK_COEF * x)));
}

fn silu_f32(x: f32) -> f32 {
    return x / (1.0 + exp(-x));
}

fn tanh_f32(x: f32) -> f32 {
    return tanh(x);
}

fn relu_f32(x: f32) -> f32 {
    return max(x, 0.0);
}

fn sigmoid_f32(x: f32) -> f32 {
    return 1.0 / (1.0 + exp(-x));
}

fn hard_sigmoid_f32(x: f32) -> f32 {
    return min(1.0, max(0.0, (x + 3.0) / 6.0));
}

fn hard_swish_f32(x: f32) -> f32 {
    return x * min(1.0, max(0.0, (x + 3.0) / 6.0));
}

fn sqr_f32(x: f32) -> f32 {
    return x * x;
}

fn sqrt_f32(x: f32) -> f32 {
    return sqrt(x);
}

fn log_f32(x: f32) -> f32 {
    return log(x);
}

fn placeholder(x: f32) -> f32 {
    return x;
}

// Unary ops with extra arguments passed through the args uniform.
fn leaky_relu_f32(x: f32) -> f32 {
    return max(x, 0.0) + min(x, 0.0) * args.x;
}

fn clamp_f32(x: f32) -> f32 {
    return min(max(args.x, x), args.y);
}

fn scale_f32(x: f32) -> f32 {
    return x * args.x;
}

fn add_scalar_f32(x: f32) -> f32 {
    return x + args.x;
}

@compute @workgroup_size(64, 1, 1)
fn main(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    if (invocation_id.x < shape_src.nrows) {
        let isrc = Shape::iv(shape_src, invocation_id.x);
        let idst = Shape::iv(shape_dst, invocation_id.x);
        dst[idst] = placeholder(src[isrc]);
    }
}