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