cubecl_std/throughput/runners/
memory_direct.rs1use cubecl::prelude::*;
2use cubecl_core as cubecl;
3use cubecl_runtime::throughput::{KernelConfig, MemoryAccess, ThroughputKey};
4
5use crate::throughput::{
6 LaunchConfig,
7 memory_probe::{self, MemoryProbe},
8};
9
10pub fn build_kernel<R: Runtime>(
13 client: &ComputeClient<R>,
14 key: ThroughputKey,
15 config: LaunchConfig,
16 working_set: usize,
17) -> KernelConfig {
18 let client = client.clone();
19 let dtype = key.dtype();
20
21 let line_bytes = config.vector_size * dtype.size();
22 let probe = MemoryProbe::new(&client, config, line_bytes, MemoryAccess::Copy, working_set);
23
24 let in_handle = client.empty(probe.buffer_bytes);
25 memory_probe::prime(&client, &in_handle, probe.pool_lines, config, dtype);
26 let out_handle = client.empty(probe.buffer_bytes);
27
28 let sample = Box::new(move |iterations: usize| {
29 let start = cubecl_common::profile::Instant::now();
30 unsafe {
31 memory_direct_throughput::launch_unchecked(
32 &client,
33 CubeCount::Static(probe.cube_count as u32, 1, 1),
34 CubeDim::new(&client, config.cube_dim),
35 config.vector_size,
36 BufferArg::from_raw_parts(in_handle.clone(), probe.pool_lines),
37 BufferArg::from_raw_parts(out_handle.clone(), probe.pool_lines),
38 probe.window_lines,
39 iterations,
40 probe.blocked,
41 dtype,
42 )
43 };
44 let _ = cubecl_core::future::block_on(client.sync());
45 start.elapsed()
46 });
47
48 let ops_count = 2 * probe.window_lines * config.vector_size;
50
51 KernelConfig { sample, ops_count }
52}
53
54#[cube(launch_unchecked)]
55pub fn memory_direct_throughput<I: Numeric, N: Size>(
56 input: &[Vector<I, N>],
57 output: &mut [Vector<I, N>],
58 window: usize,
59 n_iter: usize,
60 #[comptime] blocked: bool,
61 #[define(I)] _dtype: ElemType,
62) {
63 let len = output.len();
64 let stride = CUBE_DIM as usize * CUBE_COUNT;
65
66 let steps = window.div_ceil(stride).max(1);
70
71 let mut start = 0;
82 let mut wrap = 0;
83
84 for _ in 0..n_iter {
85 for step in 0..steps {
86 let base = if blocked {
91 ABSOLUTE_POS * steps + step
92 } else {
93 ABSOLUTE_POS + (step * stride)
94 };
95
96 if base < window {
97 let mut idx = start + base;
98 if idx >= len {
99 idx -= len;
100 }
101
102 output[idx] = input[idx];
103 }
104 }
105
106 start += window;
107 if start + window > len {
110 wrap += 1;
111 if wrap >= window {
112 wrap = 0;
113 }
114 start = wrap;
115 }
116 }
117}