Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions sycl/sycl-rs/examples/kernel_launch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void iota(float start, float *ptr) {
#[tokio::main]
async fn main() -> sycl_rs::Result<()> {
let mut queue = Queue::new();
let mut device_buffer = queue.alloc_device::<f32>(1024)?.await?;
let mut device_array = queue.alloc_device::<f32>(1024)?.await?;

let kernel = queue
.get_context()
Expand All @@ -36,16 +36,16 @@ async fn main() -> sycl_rs::Result<()> {
queue.launch(
NdRange::new([1024], [16]),
&kernel,
(3.14_f32, &mut device_buffer),
(3.14_f32, &mut device_array),
)
}?
.await?;

let mut host_buffer = queue.alloc_host::<f32>(1024)?.await?;
let mut host_array = queue.alloc_host::<f32>(1024)?.await?;

queue.copy(&device_buffer, &mut host_buffer)?.await?;
queue.copy(&device_array, &mut host_array)?.await?;

for e in host_buffer.iter() {
for e in host_array.iter() {
print!("{e} ");
}
println!();
Expand Down
8 changes: 4 additions & 4 deletions sycl/sycl-rs/examples/kernel_launch_derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ void iota(float start, float *ptr) {
#[derive(KernelArgumentList)]
struct IotaArgs<'a> {
start: f32,
ptr: &'a mut SharedBuffer<f32>,
ptr: &'a mut SharedUsmBox<f32>,
}

fn main() -> sycl_rs::Result<()> {
let mut queue = Queue::new();
let mut buffer = queue.alloc_shared::<f32>(1024)?.wait()?;
let mut array = queue.alloc_shared::<f32>(1024)?.wait()?;

let kernel = queue
.get_context()
Expand All @@ -43,13 +43,13 @@ fn main() -> sycl_rs::Result<()> {
&kernel,
IotaArgs {
start: 3.14_f32,
ptr: &mut buffer,
ptr: &mut array,
},
)
}?
.wait()?;

for e in buffer.iter() {
for e in array.iter() {
print!("{e} ");
}
println!();
Expand Down
25 changes: 13 additions & 12 deletions sycl/sycl-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
//! 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_buffer = queue.alloc_device::<f32>(1024)?.wait()?;
//! let mut device_array = queue.alloc_device::<f32>(1024)?.wait()?;
//!
//! // 3. Build a SYCL kernel.
//! let kernel = queue
Expand All @@ -69,18 +69,18 @@
//! queue.launch(
//! NdRange::new([1024], [16]),
//! &kernel,
//! (3.14_f32, &mut device_buffer),
//! (3.14_f32, &mut device_array),
//! )
//! }?
//! .wait()?;
//!
//! let mut host_buffer = queue.alloc_host::<f32>(1024)?.wait()?;
//! let mut host_array = queue.alloc_host::<f32>(1024)?.wait()?;
//!
//! // 5. Copy your data to the host.
//! queue.copy(&device_buffer, &mut host_buffer)?.wait()?;
//! queue.copy(&device_array, &mut host_array)?.wait()?;
//!
//! // You can access your host data just like a normal Rust slice.
//! for e in host_buffer.iter() {
//! for e in host_array.iter() {
//! print!("{e} ");
//! }
//! println!();
Expand All @@ -90,10 +90,11 @@
//! ```
//!
//! # Safety model
//! - USM allocations are represented by a zero-cost `Buffer` type managed through RAII.
//! - Note: Unlike SYCL buffers, SYCL-rs buffers do not rely on accessors.
//! - Buffers are zero-initialized by default.
//! - Buffers can only store types that implement [`bytemuck::Pod`].
//! - USM allocations are represented by a zero-cost [`UsmBox`](crate::usmbox::UsmBox) type managed
//! through RAII.
//! - Note: `UsmBox` arrays do not rely on accessors, unlike SYCL buffers.
//! - `UsmBox`es are zero-initialized by default.
//! - `UsmBox`es 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.
//!
Expand All @@ -106,8 +107,8 @@
//! event returned by [`Queue::barrier()`](crate::queue::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 - Buffers are
//! not thread-safe. If you need a thread-safe Buffer you need to wrap it in an `Arc<Mutex<T>>`.
//! indicated by the provided [`Send`] and [`Sync`] trait implementations. However - `UsmBox`es 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:
Expand All @@ -118,7 +119,6 @@
//! - [sycl_ext_intel_queue_immediate_command_list](https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/supported/sycl_ext_intel_queue_immediate_command_list.asciidoc)
//! - [sycl_ext_oneapi_enqueue_barrier](https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/supported/sycl_ext_oneapi_enqueue_barrier.asciidoc)

pub mod buffer;
pub mod context;
pub mod device;
pub mod event;
Expand All @@ -129,6 +129,7 @@ pub mod prelude;
pub mod queue;
pub mod range;
pub mod usm;
pub mod usmbox;

pub type SyclError = cxx::Exception;
pub type Result<T> = std::result::Result<T, SyclError>;
Expand Down
2 changes: 1 addition & 1 deletion sycl/sycl-rs/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
pub use crate::{
buffer::{Buffer, DeviceBuffer, HostBuffer, SharedBuffer},
context::Context,
device::Device,
info::{self, InfoTarget},
kernel::{Kernel, KernelArgument, KernelArgumentList},
platform::Platform,
queue::Queue,
range::{NdRange, Range},
usmbox::{DeviceUsmBox, HostUsmBox, SharedUsmBox, UsmBox},
};
88 changes: 44 additions & 44 deletions sycl/sycl-rs/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ use bytemuck::Pod;
use sycl_rs_sys::{queue::ffi, types::ffi::EventPtr};

use crate::{
buffer::{
Buffer, DeviceBuffer, EnqueuedBuffer, EnqueuedDeviceBuffer, EnqueuedHostBuffer,
EnqueuedSharedBuffer, HostBuffer, SharedBuffer,
},
context::Context,
device::Device,
event::Event,
kernel::{Kernel, KernelArgumentList},
range::{NdRange, ValidDimension},
usm::{UsmAlloc, UsmAllocator},
usmbox::{
DeviceUsmBox, EnqueuedDeviceUsmBox, EnqueuedHostUsmBox, EnqueuedSharedUsmBox,
EnqueuedUsmBox, HostUsmBox, SharedUsmBox, UsmBox,
},
};

/// The `Queue` connects a host program to a single device. Programs submit tasks to a device via the
Expand All @@ -44,74 +44,74 @@ impl Queue {
ffi::get_context(&self.0).into()
}

/// Allocates zeroed memory and creates a host-side [`Buffer`] that can store an array of T.
pub fn alloc_host<T: Pod>(&mut self, len: usize) -> Result<EnqueuedHostBuffer<T>> {
/// Allocates zeroed memory and creates a host-side [`UsmBox`] that can store an array of T.
pub fn alloc_host<T: Pod>(&mut self, len: usize) -> Result<EnqueuedHostUsmBox<T>> {
unsafe {
let mut buffer = self.alloc_uninit_host(len);
self.memset(&mut buffer, 0)
.map(|event| EnqueuedBuffer::new(buffer, event))
let mut array = self.alloc_uninit_host(len);
self.memset(&mut array, 0)
.map(|event| EnqueuedUsmBox::new(array, event))
}
}

/// Allocates zeroed memory and creates a shared [`Buffer`] that can store an array of T.
pub fn alloc_shared<T: Pod>(&mut self, len: usize) -> Result<EnqueuedSharedBuffer<T>> {
/// Allocates zeroed memory and creates a shared [`UsmBox`] that can store an array of T.
pub fn alloc_shared<T: Pod>(&mut self, len: usize) -> Result<EnqueuedSharedUsmBox<T>> {
unsafe {
let mut buffer = self.alloc_uninit_shared(len);
self.memset(&mut buffer, 0)
.map(|event| EnqueuedBuffer::new(buffer, event))
let mut array = self.alloc_uninit_shared(len);
self.memset(&mut array, 0)
.map(|event| EnqueuedUsmBox::new(array, event))
}
}

/// Allocates zeroed memory and creates a device [`Buffer`] that can store an array of T.
pub fn alloc_device<T: Pod>(&mut self, len: usize) -> Result<EnqueuedDeviceBuffer<T>> {
/// Allocates zeroed memory and creates a device [`UsmBox`] that can store an array of T.
pub fn alloc_device<T: Pod>(&mut self, len: usize) -> Result<EnqueuedDeviceUsmBox<T>> {
unsafe {
let mut buffer = self.alloc_uninit_device(len);
self.memset(&mut buffer, 0)
.map(|event| EnqueuedBuffer::new(buffer, event))
let mut array = self.alloc_uninit_device(len);
self.memset(&mut array, 0)
.map(|event| EnqueuedUsmBox::new(array, event))
}
}

/// Allocates memory and creates a host-side [`Buffer`] that can store an array of T.
/// Safety: the buffer contents are uninitialized.
pub unsafe fn alloc_uninit_host<T>(&self, len: usize) -> HostBuffer<T> {
/// Allocates memory and creates a host-side [`UsmBox`] that can store an array of T.
/// Safety: the array contents are uninitialized.
pub unsafe fn alloc_uninit_host<T>(&self, len: usize) -> HostUsmBox<T> {
let allocator = UsmAllocator::from(self);
unsafe { Buffer::new(allocator, len) }
unsafe { UsmBox::new(allocator, len) }
}

/// Allocates memory and creates a shared [`Buffer`] that can store an array of T.
/// Safety: the buffer contents are uninitialized.
pub unsafe fn alloc_uninit_shared<T>(&self, len: usize) -> SharedBuffer<T> {
/// Allocates memory and creates a shared [`UsmBox`] that can store an array of T.
/// Safety: the array contents are uninitialized.
pub unsafe fn alloc_uninit_shared<T>(&self, len: usize) -> SharedUsmBox<T> {
let allocator = UsmAllocator::from(self);
unsafe { Buffer::new(allocator, len) }
unsafe { UsmBox::new(allocator, len) }
}

/// Allocates memory and creates a device-side [`Buffer`] that can store an array of T.
/// Safety: the buffer contents are uninitialized.
pub unsafe fn alloc_uninit_device<T>(&self, len: usize) -> DeviceBuffer<T> {
/// Allocates memory and creates a device-side [`UsmBox`] that can store an array of T.
/// Safety: the array contents are uninitialized.
pub unsafe fn alloc_uninit_device<T>(&self, len: usize) -> DeviceUsmBox<T> {
let allocator = UsmAllocator::from(self);
unsafe { Buffer::new(allocator, len) }
unsafe { UsmBox::new(allocator, len) }
}

/// Sets memory allocated with USM allocations.
/// Safety: the caller must make sure the underlying memory isn't being aliased somewhere else.
pub unsafe fn memset<T, A: UsmAlloc>(
&mut self,
buffer: &mut Buffer<T, A>,
array: &mut UsmBox<T, A>,
value: i32,
) -> Result<Event> {
unsafe { self.memset_with_deps(buffer, value, &[]) }
unsafe { self.memset_with_deps(array, value, &[]) }
}

/// Sets memory allocated with USM allocations after all specified events finish.
/// Safety: the caller must make sure the underlying memory isn't being aliased somewhere else.
pub unsafe fn memset_with_deps<T, A: UsmAlloc>(
&mut self,
buffer: &mut Buffer<T, A>,
array: &mut UsmBox<T, A>,
value: i32,
dep_events: &[&Event],
) -> Result<Event> {
let ptr = buffer.get_byte_ptr();
let num_bytes = buffer.get_byte_size();
let ptr = array.get_byte_ptr();
let num_bytes = array.get_byte_size();
let dep_events = dep_events
.iter()
.map(|e| EventPtr {
Expand Down Expand Up @@ -162,10 +162,10 @@ impl Queue {
unsafe { nd_range.launch(self, kernel, args) }
}

/// Copies the contents of the source buffer to the destination buffer.
/// Copies the contents of the source array to the destination array.
///
/// Panics if the source and destination buffer lengths differ.
pub fn copy<T, A1, A2>(&mut self, src: &Buffer<T, A1>, dst: &mut Buffer<T, A2>) -> Result<Event>
/// Panics if the source and destination array lengths differ.
pub fn copy<T, A1, A2>(&mut self, src: &UsmBox<T, A1>, dst: &mut UsmBox<T, A2>) -> Result<Event>
where
T: Pod,
A1: UsmAlloc,
Expand All @@ -174,14 +174,14 @@ impl Queue {
self.copy_with_deps(src, dst, &[])
}

/// Copies the contents of the source buffer to the destination buffer after all specified
/// Copies the contents of the source array to the destination array after all specified
/// events finish.
///
/// Panics if the source and destination buffer lengths differ.
/// Panics if the source and destination array lengths differ.
pub fn copy_with_deps<T, A1, A2>(
&mut self,
src: &Buffer<T, A1>,
dst: &mut Buffer<T, A2>,
src: &UsmBox<T, A1>,
dst: &mut UsmBox<T, A2>,
dep_events: &[&Event],
) -> Result<Event>
where
Expand All @@ -192,7 +192,7 @@ impl Queue {
assert_eq!(
src.get_len(),
dst.get_len(),
"source and destination buffer lengths differ"
"source and destination array lengths differ"
);

// TODO: Resolve the C++ lifetime elision issue
Expand Down
6 changes: 3 additions & 3 deletions sycl/sycl-rs/src/usm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ unsafe impl<T: UsmAllocatorKind> Allocator for UsmAllocator<T> {
}
}

/// An allocator for Device-side buffers
/// An allocator for Device-side arrays
///
/// Safety: memory allocated by this allocator cannot be accessed on the host side
#[allow(dead_code)]
Expand All @@ -80,7 +80,7 @@ impl UsmAllocatorKind for DeviceAllocator {
}
}

/// An allocator for Host-side buffers
/// An allocator for Host-side arrays
pub struct HostAllocator;

impl UsmAllocatorKind for HostAllocator {
Expand All @@ -91,7 +91,7 @@ impl UsmAllocatorKind for HostAllocator {

unsafe impl HostAccessible for UsmAllocator<HostAllocator> {}

/// An allocator for shared memory buffers
/// An allocator for shared memory arrays
pub struct SharedAllocator;

impl UsmAllocatorKind for SharedAllocator {
Expand Down
Loading