use ruda_kernel::dsl as kernel_dsl;
use ruda_kernel::dsl::prelude::*;
#[ruda(launch)]
pub(super) fn dinput<F: Float>(
grad: &Array<F>, weights: &Array<F>, offsets: &Array<u32>, out: &mut Array<F>,
columns: u32, inner: u32, #[define(F)] _dtype: StorageType,
) {
let expert = RUDA_POS_Y as usize;
let k_base = RUDA_POS_X as usize * 16;
let begin = offsets[expert] as usize;
let end = offsets[expert + 1] as usize;
let lane = UNIT_POS as usize;
let mut left = SharedMemory::<F>::new_aligned(256usize, 32usize);
let mut right = SharedMemory::<F>::new_aligned(256usize, 32usize);
let mut result = SharedMemory::<f32>::new_aligned(256usize, 32usize);
let mut row_base = begin;
while row_base < end {
let acc = cmma::Matrix::<f32>::from_value(cmma::MatrixIdent::Accumulator,
16usize,16usize,16usize,cmma::MatrixLayout::Undefined,0.0);
let mut n_base = 0usize;
while n_base < columns as usize {
#[unroll]
for i in 0usize..8usize {
let t = lane + i * 32;
let tr = t / 16;
let tc = t % 16;
let row = row_base + tr;
let n_left = n_base + tc;
let n_right = n_base + tr;
let k = k_base + tc;
let mut a = F::cast_from(0.0f32);
let mut b = F::cast_from(0.0f32);
if tr < end - row_base && n_left < columns as usize {
a = grad[row * columns as usize + n_left];
}
if n_right < columns as usize && k < inner as usize {
b = weights[(expert * columns as usize + n_right) * inner as usize + k];
}
left[t] = a;
right[tc * 16 + tr] = b;
}
sync_ruda();
let a = cmma::Matrix::<F>::from_slice(cmma::MatrixIdent::A,
16usize,16usize,16usize,cmma::MatrixLayout::RowMajor,&left.to_slice(),16);
let b = cmma::Matrix::<F>::from_slice(cmma::MatrixIdent::B,
16usize,16usize,16usize,cmma::MatrixLayout::ColMajor,&right.to_slice(),16);
cmma::execute::<F,F,f32,f32>(&a,&b,&acc,&acc);
sync_ruda();
if columns as usize - n_base <= 16 {n_base = columns as usize;}else {n_base += 16;}
}
cmma::store(&mut result.to_slice_mut(),&acc,16,cmma::MatrixLayout::RowMajor);
sync_ruda();
#[unroll]
for i in 0usize..8usize {
let t = lane + i * 32;
let row = row_base + t / 16;
let k = k_base + t % 16;
if t / 16 < end - row_base && k < inner as usize {
out[row * inner as usize + k] = F::cast_from(result[t]);
}
}
sync_ruda();
if end - row_base <= 16 {row_base = end;}else {row_base += 16;}
}
}
#[ruda(launch)]
pub(super) fn dweight<F: Float>(
input: &Array<F>, grad: &Array<F>, offsets: &Array<u32>, out: &mut Array<f32>,
columns: u32, inner: u32, #[define(F)] _dtype: StorageType,
) {
let expert = RUDA_POS_Y as usize;
let k_base = RUDA_POS_X as usize * 16;
let n_base = RUDA_POS_Z as usize * 16;
let begin = offsets[expert] as usize;
let end = offsets[expert + 1] as usize;
let lane = UNIT_POS as usize;
let mut left = SharedMemory::<F>::new_aligned(256usize,32usize);
let mut right = SharedMemory::<F>::new_aligned(256usize,32usize);
let mut result = SharedMemory::<f32>::new_aligned(256usize,32usize);
let acc = cmma::Matrix::<f32>::from_value(cmma::MatrixIdent::Accumulator,
16usize,16usize,16usize,cmma::MatrixLayout::Undefined,0.0);
let mut row_base = begin;
while row_base < end {
#[unroll]
for i in 0usize..8usize {
let t = lane + i * 32;
let tr = t / 16;
let tc = t % 16;
let row = row_base + tr;
let n = n_base + tc;
let k = k_base + tc;
let mut a = F::cast_from(0.0f32);
let mut b = F::cast_from(0.0f32);
if tr < end - row_base && n < columns as usize {
a = grad[row * columns as usize + n];
}
if tr < end - row_base && k < inner as usize {
b = input[row * inner as usize + k];
}
left[tc * 16 + tr] = a;
right[tc * 16 + tr] = b;
}
sync_ruda();
let a = cmma::Matrix::<F>::from_slice(cmma::MatrixIdent::A,
16usize,16usize,16usize,cmma::MatrixLayout::RowMajor,&left.to_slice(),16);
let b = cmma::Matrix::<F>::from_slice(cmma::MatrixIdent::B,
16usize,16usize,16usize,cmma::MatrixLayout::ColMajor,&right.to_slice(),16);
cmma::execute::<F,F,f32,f32>(&a,&b,&acc,&acc);
sync_ruda();
if end - row_base <= 16 {row_base = end;}else {row_base += 16;}
}
cmma::store(&mut result.to_slice_mut(),&acc,16,cmma::MatrixLayout::RowMajor);
sync_ruda();
#[unroll]
for i in 0usize..8usize {
let t = lane + i * 32;
let n = n_base + t / 16;
let k = k_base + t % 16;
if n < columns as usize && k < inner as usize {
out[(expert * columns as usize + n) * inner as usize + k] = result[t];
}
}
}