From a31dd4936c7bc37b8184bd8a8194e153b6826ec7 Mon Sep 17 00:00:00 2001 From: Hobofan Date: Thu, 26 Nov 2015 18:29:20 +0100 Subject: [PATCH] feat/flatbox: provide slice accessors and give more allocation responsibility to shared_memory Pull request: #2 Approved by: MichaelHirn --- src/frameworks/native/flatbox.rs | 27 ++++++++++++++- src/shared_memory.rs | 58 ++++++++++++++++++++++++++------ tests/framework_opencl_specs.rs | 28 +++------------ tests/hardware_specs.rs | 2 -- tests/shared_memory_specs.rs | 26 ++++++++++++++ 5 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 tests/shared_memory_specs.rs diff --git a/src/frameworks/native/flatbox.rs b/src/frameworks/native/flatbox.rs index 41a2e63c..5b2f34da 100644 --- a/src/frameworks/native/flatbox.rs +++ b/src/frameworks/native/flatbox.rs @@ -1,9 +1,13 @@ //! Provides a Box without any knowledge of its underlying type. + use memory::*; use std::fmt; +use std::mem; +use std::slice; /// A Box without any knowledge of its underlying type. pub struct FlatBox { + len: usize, raw_box: *mut [u8] } @@ -11,9 +15,30 @@ impl FlatBox { /// Create FlatBox from Box, consuming it. pub fn from_box(b: Box<[u8]>) -> FlatBox { FlatBox { + len: b.len(), raw_box: Box::into_raw(b) } } + + /// Access memory as slice. + /// + /// The preffered way to access native memory. + pub fn as_slice(&self) -> &[T] { + unsafe { + slice::from_raw_parts_mut(self.raw_box as *mut T, + self.len / mem::size_of::()) + } + } + + /// Access memory as mutable slice. + /// + /// The preffered way to access native memory. + pub fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + slice::from_raw_parts_mut(self.raw_box as *mut T, + self.len / mem::size_of::()) + } + } } impl Drop for FlatBox { @@ -26,7 +51,7 @@ impl Drop for FlatBox { impl fmt::Debug for FlatBox { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "") + write!(f, "FlatBox of length {}", &self.len) } } diff --git a/src/shared_memory.rs b/src/shared_memory.rs index fb8e961c..aef11e8e 100644 --- a/src/shared_memory.rs +++ b/src/shared_memory.rs @@ -17,6 +17,7 @@ use std::collections::HashMap; use device::{IDevice, DeviceType}; use memory::MemoryType; use std::marker::PhantomData; +use std::mem; #[derive(Debug)] /// Container that handles synchronization of [Memory][1] of type `T`. @@ -24,23 +25,31 @@ use std::marker::PhantomData; pub struct SharedMemory { latest_location: DeviceType, copies: HashMap, + cap: usize, phantom: PhantomData, } impl SharedMemory { - /// Create new SharedMemory from allocated [Memory][1]. + /// Create new SharedMemory from by allocating [Memory][1] on a Device. /// [1]: ../memory/index.html - pub fn new(dev: &DeviceType, copy: MemoryType) -> SharedMemory { + pub fn new(dev: &DeviceType, capacity: usize) -> SharedMemory { let mut copies = HashMap::::new(); + let copy: MemoryType; + let alloc_size = mem::size_of::() * capacity; + match *dev { + DeviceType::Native(ref cpu) => copy = MemoryType::Native(cpu.alloc_memory(alloc_size)), + DeviceType::OpenCL(ref context) => copy = MemoryType::OpenCL(context.alloc_memory(alloc_size)), + } copies.insert(dev.clone(), copy); SharedMemory { latest_location: dev.clone(), copies: copies, + cap: capacity, phantom: PhantomData, } } - /// Synchronize memory from latest location to `destination`. + /// Synchronize memory from latest location to `destination` pub fn sync(&mut self, destination: &DeviceType) -> Result<(), SharedMemoryError> { if &self.latest_location != destination { let latest = self.latest_location.clone(); @@ -50,6 +59,20 @@ impl SharedMemory { Ok(()) } + /// Get a reference to the memory copy on the provided `device`. + /// + /// Returns `None` if there is no memory copy on the device. + pub fn get(&self, device: &DeviceType) -> Option<&MemoryType> { + self.copies.get(device) + } + + /// Get a mutable reference to the memory copy on the provided `device`. + /// + /// Returns `None` if there is no memory copy on the device. + pub fn get_mut(&mut self, device: &DeviceType) -> Option<&mut MemoryType> { + self.copies.get_mut(device) + } + /// Synchronize memory from `source` device to `destination` device. fn sync_from_to(&mut self, source: &DeviceType, destination: &DeviceType) -> Result<(), SharedMemoryError> { if source != destination { @@ -67,8 +90,7 @@ impl SharedMemory { } }, } - self.add_copy(source, source_copy); - self.add_copy(destination, destination_copy); + self.return_copies(source, source_copy, destination, destination_copy); Ok(()) }, Err(err) => Err(err), @@ -78,11 +100,7 @@ impl SharedMemory { } } - /// Register a memory copy for a device. - pub fn add_copy(&mut self, dev: &DeviceType, copy: MemoryType) { - self.copies.insert(dev.clone(), copy); - } - + /// Aquire ownership over the copies for synchronizing. fn aquire_copies(&mut self, source: &DeviceType, destination: &DeviceType) -> Result<(MemoryType, MemoryType), SharedMemoryError> { let source_copy: MemoryType; let destination_copy: MemoryType; @@ -98,6 +116,26 @@ impl SharedMemory { Ok((source_copy, destination_copy)) } + /// Return ownership over the copies after synchronizing. + fn return_copies(&mut self, src: &DeviceType, src_mem: MemoryType, dest: &DeviceType, dest_mem: MemoryType) { + self.copies.insert(src.clone(), src_mem); + self.copies.insert(dest.clone(), dest_mem); + } + + /// Track a new device and allocate memory on it. + pub fn add_device(&mut self, dev: &DeviceType) { + let copy: MemoryType; + match *dev { + DeviceType::Native(ref cpu) => copy = MemoryType::Native(cpu.alloc_memory(mem::size_of::())), + DeviceType::OpenCL(ref context) => copy = MemoryType::OpenCL(context.alloc_memory(mem::size_of::())), + } + self.copies.insert(dev.clone(), copy); + } + + /// Returns the number of elements for which the SharedMemory has been allocated. + pub fn capacity(&self) -> usize { + self.cap + } } /// Errors than can occur when synchronizing memory. diff --git a/tests/framework_opencl_specs.rs b/tests/framework_opencl_specs.rs index 42ffadd0..4874b973 100644 --- a/tests/framework_opencl_specs.rs +++ b/tests/framework_opencl_specs.rs @@ -8,8 +8,6 @@ mod framework_opencl_spec { use co::frameworks::OpenCL; use co::frameworks::opencl::memory::*; - use co::memory::*; - #[test] fn it_works() { let frm = OpenCL::new(); @@ -25,28 +23,10 @@ mod framework_opencl_spec { #[test] fn it_allocates_memory() { - // let (device, ctx, queue) = create_compute_context().unwrap(); - - //let vec_a = vec![0isize, 1, 2, -3, 4, 5, 6, 7]; - //let frm = OpenCL::new(); - //let ctx = frm.new_device(frm.hardwares()[0..1].to_vec()).unwrap(); + let vec_a = vec![0isize, 1, 2, -3, 4, 5, 6, 7]; + let frm = OpenCL::new(); + let ctx = frm.new_device(frm.hardwares()[0..1].to_vec()).unwrap(); // OpenCL memory - // let ctx_ptr = ctx.ctx as *mut libc::c_void; - //let res = Memory::>::new(ctx.id_c(), vec_a.len()); - // pinned host memory - //let bx = Box::new(vec_a.clone()); - //let res = Memory::>::from_box(ctx.id_c(), bx); - } - - #[test] - fn it_creates_buffer() { - // let vec_a = vec![0isize, 1, 2, -3, 4, 5, 6, 7]; - // let mut buf = Buffer::new(); - // - // let frm = OpenCL::new(); - // let dev = frm.new_device(frm.hardwares()[0..1].to_vec()).unwrap(); - // let mem = &mut dev.alloc_memory::(vec_a.len()); - // - // buf.add_copy(&dev, mem); + let res = Memory::new(ctx.id_c(), vec_a.len()); } } diff --git a/tests/hardware_specs.rs b/tests/hardware_specs.rs index 5343456b..481ee9d0 100644 --- a/tests/hardware_specs.rs +++ b/tests/hardware_specs.rs @@ -3,7 +3,6 @@ extern crate libc; #[cfg(test)] mod hardware_spec { - use co::hardware::{IHardware, HardwareType}; use co::frameworks::opencl::Device; @@ -58,5 +57,4 @@ mod hardware_spec { _ => false }); } - } diff --git a/tests/shared_memory_specs.rs b/tests/shared_memory_specs.rs new file mode 100644 index 00000000..61201455 --- /dev/null +++ b/tests/shared_memory_specs.rs @@ -0,0 +1,26 @@ +extern crate collenchyma as co; +extern crate libc; + +#[cfg(test)] +mod shared_memory_spec { + + use co::framework::IFramework; + use co::frameworks::Native; + + use co::device::{IDevice, DeviceType}; + use co::memory::MemoryType; + + use co::shared_memory::*; + + #[test] + fn it_creates_buffer() { + let ntv = Native::new(); + let cpu = ntv.new_device(ntv.hardwares()).unwrap(); + let cpu_dev = &mut DeviceType::Native(cpu.clone()); + let shared_data = &mut SharedMemory::::new(cpu_dev, 10); + if let &MemoryType::Native(ref dat) = shared_data.get(cpu_dev).unwrap() { + let data = dat.as_slice::(); + assert_eq!(10, data.len()); + } + } +}