1use ruda_kernel::dsl as kernel_dsl;
2use ruda_kernel::dsl::prelude::*;
3use super::{RudaUnaryOp, RudaUnaryOpExpand};
4use super::record::{RudaRead, RudaReadExpand, RudaWrite, RudaWriteExpand};
5
6#[ruda]
8pub fn index(lane: usize, item: usize, #[comptime] lanes: usize, #[comptime] items: usize,
9 #[comptime] striped: bool, #[comptime] warp_striped: bool, #[comptime] width: usize,
10) -> usize {
11 if warp_striped { lane / width * width * items + item * width + lane % width }
12 else if striped { item * lanes + lane }
13 else { lane * items + item }
14}
15
16#[ruda]
19pub fn load<T: RudaType, U: RudaType + Copy, I: RudaRead<T>, W: RudaWrite<U>, O: RudaUnaryOp<T, U>>(
20 input: &I, output: &mut W, convert: &O, offset: usize, valid: usize, lane: usize, padding: U,
21 #[comptime] lanes: usize, #[comptime] items: usize, #[comptime] striped: bool,
22 #[comptime] warp_striped: bool, #[comptime] width: usize, #[comptime] pad: bool,
23) {
24 #[unroll]
25 for item in 0..items {
26 let position = index(lane, item, lanes, items, striped, warp_striped, width);
27 if position < valid { output.write(item, convert.apply(input.read(offset + position))); }
28 else if pad { output.write(item, padding); }
29 }
30}
31
32#[ruda]
33pub fn store<T: RudaType, U: RudaType, I: RudaRead<T>, W: RudaWrite<U>, O: RudaUnaryOp<T, U>>(
34 input: &I, output: &mut W, convert: &O, offset: usize, valid: usize, lane: usize,
35 #[comptime] lanes: usize, #[comptime] items: usize, #[comptime] striped: bool,
36 #[comptime] warp_striped: bool, #[comptime] width: usize,
37) {
38 #[unroll]
39 for item in 0..items {
40 let position = index(lane, item, lanes, items, striped, warp_striped, width);
41 if position < valid { output.write(offset + position, convert.apply(input.read(item))); }
42 }
43}
44
45#[ruda]
49pub fn exchange<T: RudaType, I: RudaRead<T>, W: RudaWrite<T>, S: RudaWrite<T>>(
50 input: &I, output: &mut W, scratch: &mut S, lane: usize, base: usize,
51 #[comptime] lanes: usize, #[comptime] items: usize, #[comptime] width: usize,
52 #[comptime] input_striped: bool, #[comptime] input_warp_striped: bool,
53 #[comptime] output_striped: bool, #[comptime] output_warp_striped: bool, #[comptime] warp_scope: bool,
54) {
55 #[unroll]
56 for item in 0..items {
57 let position = index(lane, item, lanes, items, input_striped, input_warp_striped, width);
58 scratch.write(base + position, input.read(item));
59 }
60 if warp_scope { sync_plane(); } else { sync_ruda(); }
61 #[unroll]
62 for item in 0..items {
63 let position = index(lane, item, lanes, items, output_striped, output_warp_striped, width);
64 output.write(item, scratch.read(base + position));
65 }
66 if warp_scope { sync_plane(); } else { sync_ruda(); }
67}
68
69#[ruda]
73pub fn scatter<T: RudaType, I: RudaRead<T>, W: RudaWrite<T>, S: RudaWrite<T>>(
74 input: &I, ranks: &Array<i64>, flags: &Array<bool>, output: &mut W, scratch: &mut S,
75 lane: usize, base: usize, #[comptime] lanes: usize, #[comptime] items: usize, #[comptime] width: usize,
76 #[comptime] striped: bool, #[comptime] warp_striped: bool, #[comptime] guarded: bool,
77 #[comptime] flagged: bool, #[comptime] warp_scope: bool,
78) {
79 #[unroll]
80 for item in 0..items {
81 let rank = ranks[item];
82 let mut valid = true;
83 if guarded { valid = rank >= 0 && (rank as u64) < (lanes * items) as u64; }
84 if flagged { valid = valid && flags[item]; }
85 if valid { scratch.write(base + rank as usize, input.read(item)); }
86 }
87 if warp_scope { sync_plane(); } else { sync_ruda(); }
88 #[unroll]
89 for item in 0..items {
90 let position = index(lane, item, lanes, items, striped, warp_striped, width);
91 output.write(item, scratch.read(base + position));
92 }
93 if warp_scope { sync_plane(); } else { sync_ruda(); }
94}
95
96#[derive(Clone, Copy, RudaType, RudaLaunch)]
97pub struct RudaIdentity;
98
99impl<R: Runtime> Clone for RudaIdentityLaunch<R> {
100 fn clone(&self) -> Self { Self::new() }
101}
102
103#[ruda]
104impl<T: RudaType> RudaUnaryOp<T, T> for RudaIdentity {
105 fn apply(&self, value: T) -> T { value }
106}