cubecl_std/throughput/runners/
memory_direct.rs1use cubecl::prelude::*;
2use cubecl_core as cubecl;
3use cubecl_runtime::throughput::{KernelConfig, MemorySpec, ThroughputError, ThroughputKey};
4
5use crate::throughput::{
6 LaunchConfig,
7 memory_probe::{self, MemoryProbe},
8};
9
10pub fn build_kernel(
13 client: &Client,
14 key: ThroughputKey,
15 config: LaunchConfig,
16 spec: MemorySpec,
17) -> Result<KernelConfig, ThroughputError> {
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, spec);
23
24 let [in_handle, out_handle] =
25 memory_probe::reserve(&client, [probe.buffer_bytes, probe.buffer_bytes])?;
26 memory_probe::prime(&client, &in_handle, probe.pool_lines, config, dtype);
27
28 let (verifier, written) = (client.clone(), out_handle.clone());
29 let sample = Box::new(move |iterations: usize| {
30 let start = cubecl_common::profile::Instant::now();
31 unsafe {
32 memory_direct_throughput::launch_unchecked(
33 &client,
34 CubeCount::Static(probe.cube_count as u32, 1, 1),
35 config.cube_dim,
36 config.vector_size,
37 BufferArg::from_raw_parts(in_handle.clone(), probe.pool_lines),
38 BufferArg::from_raw_parts(out_handle.clone(), probe.pool_lines),
39 probe.window_lines,
40 iterations,
41 probe.blocked,
42 dtype,
43 )
44 };
45 let _ = cubecl_core::future::block_on(client.sync());
47 start.elapsed()
48 });
49 memory_probe::verify(&verifier, &sample, &written)?;
50
51 let ops_count = 2 * probe.window_lines * config.vector_size;
53
54 Ok(KernelConfig {
55 sample,
56 ops_count,
57 min_iterations: probe.min_iterations(),
58 })
59}
60
61#[cube(launch_unchecked)]
62pub fn memory_direct_throughput<I: Numeric, N: Size>(
63 input: &[Vector<I, N>],
64 output: &mut [Vector<I, N>],
65 window: usize,
66 n_iter: usize,
67 #[comptime] blocked: bool,
68 #[define(I)] _dtype: ElemType,
69) {
70 let len = output.len();
71 let stride = CUBE_DIM as usize * CUBE_COUNT;
72
73 let steps = window.div_ceil(stride).max(1);
77
78 let mut start = 0;
89
90 for _ in 0..n_iter {
91 for step in 0..steps {
92 let base = if blocked {
97 ABSOLUTE_POS * steps + step
98 } else {
99 ABSOLUTE_POS + (step * stride)
100 };
101
102 if base < window {
103 let mut idx = start + base;
104 if idx >= len {
105 idx -= len;
106 }
107
108 output[idx] = input[idx];
109 }
110 }
111
112 start += window;
113 if start >= len {
114 start -= len;
115 }
116 }
117}