Expand description
§SYCL-rs
SYCL-rs is a set of (mostly) safe Rust bindings for SYCL - an open, royalty-free, cross-platform abstraction layer that enables code for heterogeneous and offload processors to be written using modern ISO C++, and provides APIs and abstractions to find devices (CPUs, GPUs, FPGAs …) on which code can be executed, and to manage data resources and code execution on those devices.
§System dependencies
Make sure to install the Intel oneAPI toolkit.
Then source the setvars.sh file:
source <oneapi_install_directory>/setvars.shThis project was tested on oneAPI Toolkit 2026.1 and requires the Unified Runtime over Level Zero driver version 1.14.37020 or newer. For more detailed information check out the required extensions section.
§Getting started
§Building the crate
Before building this crate you need to source the setvars.sh file. You can then build it as
usual with cargo:
cargo build --releaseYou must also source setvars.sh before running any SYCL program.
§Hello world
fn main() -> sycl_rs::Result<()> {
// 1. Create a Queue. It's the main entry point to the SYCL API.
let mut queue = Queue::new();
let mut device_array = queue.alloc_device::<f32>(1024)?.wait()?;
// 3. Build a SYCL kernel.
let kernel = queue
.get_context()
.create_kernel_bundle_from_source(IOTA_SRC)?
.build()?
.get_kernel("iota")?;
// 4. Launch your kernel.
unsafe {
queue.launch(
NdRange::new([1024], [16]),
&kernel,
(3.14_f32, &mut device_array),
)
}?
.wait()?;
let mut host_array = queue.alloc_host::<f32>(1024)?.wait()?;
// 5. Copy your data to the host.
queue.copy(&device_array, &mut host_array)?.wait()?;
// You can access your host data just like a normal Rust slice.
for e in host_array.iter() {
print!("{e} ");
}
println!();
Ok(())
}§Safety model
- USM allocations are represented by a zero-cost
UsmBoxtype managed through RAII.- Note:
UsmBoxarrays do not rely on accessors, unlike SYCL buffers.
- Note:
UsmBoxes are zero-initialized by default.UsmBoxes can only store types that implement [bytemuck::Pod].- Kernel launch is inherently unsafe. In particular, the caller must ensure that every argument has the correct representation, layout, and alignment.
§Asynchronous programming model
Each queue operation returns an Event. You can synchronously
.wait() for it, or asynchronously .await it.
You can also synchronously call Queue::wait() to wait for a
Queue directly. To do the same asynchronously you have to .await an
event returned by Queue::barrier().
All basic SYCL wrapper types (Queue, Event, Context, Platform, Device) are thread safe as
indicated by the provided Send and Sync trait implementations. However - UsmBoxes are
not thread-safe. If you need a thread-safe UsmBox you need to wrap it in an Arc<Mutex<T>>.
§Required extensions
This project requires the following SYCL extensions to work:
The following extensions are also required for async support: