pub struct Task<'a> { /* private fields */ }
Expand description
Represents an MCL task whose kernel has been set but the arguments and target device are missing
Implementations§
Source§impl<'a> Task<'a>
impl<'a> Task<'a>
Sourcepub fn arg(self, arg: TaskArg<'a>) -> Self
pub fn arg(self, arg: TaskArg<'a>) -> Self
Set a new argument arg
for this
mcl task.
Note the order in which tasks are set must match the order expected by the kernel
Returns the Task with the arg set
§Examples
let mcl = mcl_rs::MclEnvBuilder::new().initialize();
mcl.create_prog("my_prog",mcl_rs::PrgType::Src)
.with_compile_args("-D MYDEF").load();
let data = vec![0; 4];
let mut out = vec![0; 4];
let pes: [u64; 3] = [1, 1, 1];
let mcl_future = mcl.task("my_kernel", 1)
.arg(mcl_rs::TaskArg::input_slice(&data)) //the first argument to the kernel is the input array
.arg(mcl_rs::TaskArg::output_slice(&mut out))//the second argument to the kernel is the output array
.exec(pes);
futures::executor::block_on(mcl_future);
Sourcepub fn arg_buffer(self, buffer: RegisteredBuffer<'a>) -> Self
pub fn arg_buffer(self, buffer: RegisteredBuffer<'a>) -> Self
Set a new argument registered buffer arg
for this
mcl task in preparation
Returns the Task with the arg set
§Examples
let mcl = mcl_rs::MclEnvBuilder::new().initialize();
mcl.create_prog("my_prog",mcl_rs::PrgType::Src)
.with_compile_args("-D MYDEF").load();
let mut a = vec![0;100];
let buf = mcl.register_buffer(mcl_rs::TaskArg::inout_slice(&mut a)
.resident(true)
.dynamic(true),
);
let pes: [u64; 3] = [1, 1, 1];
let mcl_future = mcl.task("my_kernel", 1)
.arg_buffer(buf)
.exec(pes);
futures::executor::block_on(mcl_future);
Available on crate features shared_mem
or pocl_extensions
only.
shared_mem
or pocl_extensions
only.Set a new shared argument buffer arg
for this
mcl task in preparation
Returns the Task with the arg set
§Saftey
We track the reader and writers associated with this buffer to protect access, but that only applies to this process
Regardless of and local saftey guarentees we provide, using a shared buffer is still inherently unsafe as this represents a multi-processed shared memory buffer, managed by the MCL c-library, no guarantees can be provided on multiple processes modifying this buffer simultaneously
§Examples
let mcl = mcl_rs::MclEnvBuilder::new().initialize();
mcl.create_prog("my_prog",mcl_rs::PrgType::Src)
.with_compile_args("-D MYDEF").load();
let num_elems = 100;
let buf = mcl.create_shared_buffer(mcl_rs::TaskArg::inout_shared::<u32>("my_buffer", num_elems));
let pes: [u64; 3] = [1, 1, 1];
let mcl_future = unsafe {
mcl.task("my_kernel", 1)
.arg_shared(buf) //potentially accessed by other proccesses hence unsafe
.exec(pes)
};
futures::executor::block_on(mcl_future);
Sourcepub fn lwsize(self, les: [u64; 3]) -> Self
pub fn lwsize(self, les: [u64; 3]) -> Self
Set the local workgroup size les
to the mcl task in preparation
Returns the Task with the local workgroup size set
§Examples
let mcl = mcl_rs::MclEnvBuilder::new().initialize();
mcl.create_prog("my_prog",mcl_rs::PrgType::Src)
.with_compile_args("-D MYDEF").load();
let data = vec![0; 4];
let les: [u64; 3] = [1, 1, 1];
let pes: [u64; 3] = [1, 1, 1];
let mcl_future = mcl.task("my_kernel", 1)
.arg(mcl_rs::TaskArg::input_slice(&data))
.lwsize(les)
.exec(pes);
futures::executor::block_on(mcl_future);
Sourcepub fn dev(self, dev: DevType) -> Self
pub fn dev(self, dev: DevType) -> Self
Set the preferred device dev
to the mcl task in preparation
Returns the Task with the desired device set
§Examples
let mcl = mcl_rs::MclEnvBuilder::new().initialize();
mcl.create_prog("my_prog",mcl_rs::PrgType::Src)
.with_compile_args("-D MYDEF").load();
let data = vec![0; 4];
let les: [u64; 3] = [1, 1, 1];
let pes: [u64; 3] = [1, 1, 1];
let mcl_future = mcl.task("my_kernel", 1)
.arg(mcl_rs::TaskArg::input_slice(&data))
.lwsize(les)
.dev(mcl_rs::DevType::CPU)
.exec(pes);
futures::executor::block_on(mcl_future);
Available on crate features shared_mem
or pocl_extensions
only.
shared_mem
or pocl_extensions
only.If this is a shared task return the task id otherwise return None
§Examples
let mcl = mcl_rs::MclEnvBuilder::new().initialize();
mcl.load_prog("my_prog",mcl_rs::PrgType::Src);
let data = vec![0; 4];
let pes: [u64; 3] = [1, 1, 1];
let task = mcl.task("my_kernel", 1);
assert_eq!(task.shared_id(), None);
let shared_task = mcl.shared_task("my_kernel2", 1);
assert!(shared_task.shared_id().is_some());
Sourcepub async fn exec(self, pes: [u64; 3])
pub async fn exec(self, pes: [u64; 3])
Submit the task for execution
This is an asynchronous operation, meaning that no work is actually performed until
the returned future is actualy await
ed.
While awaiting a task execution, the user application will not make forward progress until
the underylying device has executed the task and performed any necessary data transfers.
Upon return from the await call, any output data is gauranteed to be written to its approriate buffer.
Task execution order can be enforced by sequentially awaiting tasks, or may be executed simultaneously using data structures such as Join_all https://docs.rs/futures/latest/futures/future/fn.join_all.html
§Examples
let mcl = mcl_rs::MclEnvBuilder::new().num_workers(10).initialize();
mcl.load_prog("my_path", mcl_rs::PrgType::Src);
let data = vec![0; 4];
let pes: [u64; 3] = [1, 1, 1];
let task_1 = mcl.task("my_kernel", 1)
.arg(mcl_rs::TaskArg::input_slice(&data))
.dev(mcl_rs::DevType::CPU)
.exec(pes); //this creates a future we need to await
let task_2 = mcl.task("my_kernel", 1)
.arg(mcl_rs::TaskArg::input_slice(&data))
.dev(mcl_rs::DevType::CPU)
.exec(pes); //this creates a future we need to await
let sequential_tasks = async move{
task_1.await; //task will execute before task 2 is even submitted
task_2.await;
};
futures::executor::block_on(sequential_tasks);
let task_3 = mcl.task("my_kernel", 1)
.arg(mcl_rs::TaskArg::input_slice(&data))
.dev(mcl_rs::DevType::CPU)
.exec(pes); //this creates a future we need to await
let task_4 = mcl.task("my_kernel", 1)
.arg(mcl_rs::TaskArg::input_slice(&data))
.dev(mcl_rs::DevType::CPU)
.exec(pes); //this creates a future we need to await
let simultaneous_tasks = futures::future::join_all([task_3,task_4]);
futures::executor::block_on(simultaneous_tasks); //both tasks submitted "simultaneously"