ruDNN 0.1.30

Neural network operators for Ruda.
Documentation
use ruda_kernel::dsl as kernel_dsl;
use ruda_kernel::dsl::prelude::*;

#[ruda(launch)]
pub(crate) fn softmax<F: Float>(
    logits: &Array<F>,
    probabilities: &mut Array<f32>,
    experts: u32,
    #[define(F)] _dtype: StorageType,
) {
    let token = ABSOLUTE_POS;
    let e = experts as usize;
    if token >= logits.len() / e {
        terminate!();
    }
    let start = token * e;
    let mut maximum = f32::cast_from(logits[start]);
    let mut i = 1usize;
    while i < e {
        maximum = f32::max(maximum, f32::cast_from(logits[start + i]));
        i += 1;
    }
    let mut sum = 0.0f32;
    i = 0;
    while i < e {
        let probability = f32::exp(f32::cast_from(logits[start + i]) - maximum);
        probabilities[start + i] = probability;
        sum += probability;
        i += 1;
    }
    i = 0;
    while i < e {
        probabilities[start + i] = probabilities[start + i] / sum;
        i += 1;
    }
}

#[ruda(launch)]
pub(crate) fn topk<F: Float>(
    probabilities: &Array<f32>,
    indices: &mut Array<u32>,
    weights: &mut Array<F>,
    experts: u32,
    top_k: u32,
    renormalize: u32,
    #[define(F)] _dtype: StorageType,
) {
    let token = ABSOLUTE_POS;
    let e = experts as usize;
    let k = top_k as usize;
    if token >= probabilities.len() / e {
        terminate!();
    }
    let mut previous_value = 0.0f32;
    let mut previous_id = 0usize;
    let mut selected_sum = 0.0f32;
    let mut slot = 0usize;
    while slot < k {
        let mut found = false;
        let mut best = 0.0f32;
        let mut best_id = 0usize;
        let mut expert = 0usize;
        while expert < e {
            let value = probabilities[token * e + expert];
            let nan = value != value;
            let eligible = slot == 0
                || value < previous_value
                || ((value == previous_value || nan) && expert > previous_id);
            if eligible && (!found || value > best) {
                found = true;
                best = value;
                best_id = expert;
            }
            expert += 1;
        }
        indices[token * k + slot] = best_id as u32;
        selected_sum += best;
        previous_value = best;
        previous_id = best_id;
        slot += 1;
    }
    slot = 0;
    while slot < k {
        let expert = indices[token * k + slot] as usize;
        let mut weight = probabilities[token * e + expert];
        if renormalize != 0 {
            weight = weight / selected_sum;
        }
        weights[token * k + slot] = F::cast_from(weight);
        slot += 1;
    }
}