use crate::{self as cubecl};
use cubecl::prelude::*;
use cubecl_environment::stream::StreamId;
use cubecl_runtime::runtime::Runtime;
#[cube(launch)]
fn add_one(input: &[f32], output: &mut [f32]) {
if ABSOLUTE_POS < output.len() {
output[ABSOLUTE_POS] = input[ABSOLUTE_POS] + 1.0;
}
}
pub fn a_capture_is_seen_by_every_client_of_its_stream<R: Runtime>() {
let client = R::client(&Default::default());
let other_client = R::client(&Default::default());
let owner = StreamId { value: 3_000_001 };
let neighbour = StreamId { value: 3_000_002 };
let capturing = |client: &Client, stream: StreamId| stream.executes(|| client.is_capturing());
let n = 4usize;
let (input, output) = owner.executes(|| {
(
client.create_from_slice(f32::as_bytes(&[1.0, 2.0, 3.0, 4.0])),
client.empty(n * core::mem::size_of::<f32>()),
)
});
let run = || {
add_one::launch(
&client,
CubeCount::Static(1, 1, 1),
CubeDim::new(&client, n),
unsafe { BufferArg::from_raw_parts(input.clone(), n) },
unsafe { BufferArg::from_raw_parts(output.clone(), n) },
);
};
owner.executes(|| {
run();
client.read_one(output.clone()).unwrap();
});
assert!(!capturing(&client, owner), "no capture before prepare");
owner
.executes(|| client.graph_prepare())
.expect("graph_prepare");
assert!(capturing(&client, owner), "the warmup run is part of it");
assert!(
capturing(&other_client, owner),
"every client of the stream sees it"
);
assert!(
!capturing(&client, neighbour),
"another stream isn't capturing"
);
owner.executes(|| {
run();
client.read_one(output.clone()).unwrap();
client.start_capture().expect("start_capture");
});
assert!(
capturing(&other_client, owner),
"the recorded run is part of it"
);
assert!(!capturing(&other_client, neighbour));
let graph = owner.executes(|| {
run();
client.stop_capture()
});
graph.expect("stop_capture");
assert!(
!capturing(&client, owner),
"the capture ends with stop_capture"
);
assert!(!capturing(&other_client, owner));
}
pub fn a_prepared_capture_ends_at_stop_capture<R: Runtime>() {
let client = R::client(&Default::default());
let owner = StreamId { value: 3_000_003 };
let capturing = || owner.executes(|| client.is_capturing());
owner
.executes(|| client.graph_prepare())
.expect("graph_prepare");
assert!(capturing(), "the warmup run is part of the capture");
owner
.executes(|| client.stop_capture())
.expect_err("nothing recorded, so there is no graph to seal");
assert!(!capturing(), "the capture ended with stop_capture");
let n = 4usize;
let (input, output) = owner.executes(|| {
(
client.create_from_slice(f32::as_bytes(&[1.0, 2.0, 3.0, 4.0])),
client.empty(n * core::mem::size_of::<f32>()),
)
});
let run = || {
add_one::launch(
&client,
CubeCount::Static(1, 1, 1),
CubeDim::new(&client, n),
unsafe { BufferArg::from_raw_parts(input.clone(), n) },
unsafe { BufferArg::from_raw_parts(output.clone(), n) },
);
};
let out = owner.executes(|| {
client
.graph_prepare()
.expect("the stream can be prepared again");
run();
client.read_one(output.clone()).unwrap();
client.start_capture().expect("start_capture");
run();
let graph = client.stop_capture().expect("stop_capture");
unsafe { graph.replay() }.expect("replay enqueues");
client.read_one(output.clone()).unwrap()
});
assert_eq!(f32::from_bytes(&out), &[2.0, 3.0, 4.0, 5.0]);
assert!(!capturing());
}