Skip to content

Commit

Permalink
feat/flatbox: provide slice accessors
Browse files Browse the repository at this point in the history
and give more allocation responsibility to shared_memory

Pull request: #2
Approved by: MichaelHirn
  • Loading branch information
hobofan authored and homu committed Nov 27, 2015
1 parent d61cb56 commit a31dd49
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 37 deletions.
27 changes: 26 additions & 1 deletion src/frameworks/native/flatbox.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
//! 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]
}

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<T>(&self) -> &[T] {
unsafe {
slice::from_raw_parts_mut(self.raw_box as *mut T,
self.len / mem::size_of::<T>())
}
}

/// Access memory as mutable slice.
///
/// The preffered way to access native memory.
pub fn as_mut_slice<T>(&mut self) -> &mut [T] {
unsafe {
slice::from_raw_parts_mut(self.raw_box as *mut T,
self.len / mem::size_of::<T>())
}
}
}

impl Drop for FlatBox {
Expand All @@ -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)
}
}

Expand Down
58 changes: 48 additions & 10 deletions src/shared_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,39 @@ 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`.
/// [1]: ../memory/index.html
pub struct SharedMemory<T> {
latest_location: DeviceType,
copies: HashMap<DeviceType, MemoryType>,
cap: usize,
phantom: PhantomData<T>,
}

impl<T> SharedMemory<T> {
/// 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<T> {
pub fn new(dev: &DeviceType, capacity: usize) -> SharedMemory<T> {
let mut copies = HashMap::<DeviceType, MemoryType>::new();
let copy: MemoryType;
let alloc_size = mem::size_of::<T>() * 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();
Expand All @@ -50,6 +59,20 @@ impl<T> SharedMemory<T> {
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 {
Expand All @@ -67,8 +90,7 @@ impl<T> SharedMemory<T> {
}
},
}
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),
Expand All @@ -78,11 +100,7 @@ impl<T> SharedMemory<T> {
}
}

/// 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;
Expand All @@ -98,6 +116,26 @@ impl<T> SharedMemory<T> {
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::<T>())),
DeviceType::OpenCL(ref context) => copy = MemoryType::OpenCL(context.alloc_memory(mem::size_of::<T>())),
}
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.
Expand Down
28 changes: 4 additions & 24 deletions tests/framework_opencl_specs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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::<Vec<isize>>::new(ctx.id_c(), vec_a.len());
// pinned host memory
//let bx = Box::new(vec_a.clone());
//let res = Memory::<Vec<isize>>::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::<isize>(vec_a.len());
//
// buf.add_copy(&dev, mem);
let res = Memory::new(ctx.id_c(), vec_a.len());
}
}
2 changes: 0 additions & 2 deletions tests/hardware_specs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ extern crate libc;

#[cfg(test)]
mod hardware_spec {

use co::hardware::{IHardware, HardwareType};
use co::frameworks::opencl::Device;

Expand Down Expand Up @@ -58,5 +57,4 @@ mod hardware_spec {
_ => false
});
}

}
26 changes: 26 additions & 0 deletions tests/shared_memory_specs.rs
Original file line number Diff line number Diff line change
@@ -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::<f32>::new(cpu_dev, 10);
if let &MemoryType::Native(ref dat) = shared_data.get(cpu_dev).unwrap() {
let data = dat.as_slice::<f32>();
assert_eq!(10, data.len());
}
}
}

0 comments on commit a31dd49

Please sign in to comment.