use ruda_kernel::dsl as kernel_dsl;
use ruda_kernel::dsl::prelude::*;
#[ruda]
pub fn transpose<T: RudaPrimitive>(
input: &Array<T>,
output: &mut Array<T>,
scratch: &mut SharedMemory<T>,
#[comptime] threads: usize,
#[comptime] items_per_thread: usize,
#[comptime] blocked_to_striped: bool,
) {
let lane = UNIT_POS as usize;
#[unroll]
for item in 0..items_per_thread {
let index = if blocked_to_striped { lane * items_per_thread + item } else { item * threads + lane };
scratch[index] = input[item];
}
sync_ruda();
#[unroll]
for item in 0..items_per_thread {
let index = if blocked_to_striped { item * threads + lane } else { lane * items_per_thread + item };
output[item] = scratch[index];
}
sync_ruda();
}
#[ruda]
pub fn scatter<T: RudaPrimitive>(
input: &Array<T>,
ranks: &Array<u32>,
output: &mut Array<T>,
scratch: &mut SharedMemory<T>,
#[comptime] threads: usize,
#[comptime] items_per_thread: usize,
#[comptime] striped: bool,
) {
#[unroll]
for item in 0..items_per_thread {
let rank = ranks[item] as usize;
scratch[rank] = input[item];
}
sync_ruda();
#[unroll]
for item in 0..items_per_thread {
let index = if striped { item * threads + UNIT_POS as usize } else { UNIT_POS as usize * items_per_thread + item };
output[item] = scratch[index];
}
sync_ruda();
}
#[ruda]
pub fn warp_transpose<T: RudaPrimitive>(
input: &Array<T>, output: &mut Array<T>, scratch: &mut SharedMemory<T>,
#[comptime] threads: usize, #[comptime] items_per_thread: usize,
#[comptime] width: usize, #[comptime] blocked_to_warp_striped: bool,
) {
let thread = UNIT_POS as usize;
let first = thread / width * width;
let lane = thread - first;
let lanes = min(width, threads - first);
#[unroll]
for item in 0..items_per_thread {
let blocked = thread * items_per_thread + item;
let striped = first * items_per_thread + item * lanes + lane;
let index = if blocked_to_warp_striped { blocked } else { striped };
scratch[index] = input[item];
}
sync_ruda();
#[unroll]
for item in 0..items_per_thread {
let blocked = thread * items_per_thread + item;
let striped = first * items_per_thread + item * lanes + lane;
let index = if blocked_to_warp_striped { striped } else { blocked };
output[item] = scratch[index];
}
sync_ruda();
}
#[ruda]
pub fn scatter_flagged<T: RudaPrimitive, I: Int>(
input: &Array<T>, ranks: &Array<I>, valid: &Array<bool>, output: &mut Array<T>,
scratch: &mut SharedMemory<T>, #[comptime] threads: usize, #[comptime] items_per_thread: usize,
) {
#[unroll]
for item in 0..items_per_thread {
if valid[item] {
let rank = usize::cast_from(ranks[item]);
scratch[rank] = input[item];
}
}
sync_ruda();
#[unroll]
for item in 0..items_per_thread { output[item] = scratch[item * threads + UNIT_POS as usize]; }
sync_ruda();
}
#[ruda]
pub fn scatter_guarded<T: RudaPrimitive, I: Int>(
input: &Array<T>, ranks: &Array<I>, output: &mut Array<T>, scratch: &mut SharedMemory<T>,
#[comptime] threads: usize, #[comptime] items_per_thread: usize,
) {
let mut valid = Array::<bool>::new(items_per_thread);
#[unroll]
for item in 0..items_per_thread { valid[item] = ranks[item] >= I::from_int(0); }
scatter_flagged(input, ranks, &valid, output, scratch, threads, items_per_thread);
}