Skip to content

Commit

Permalink
feat/lib: add foundation of the library design
Browse files Browse the repository at this point in the history
  • Loading branch information
hobofan authored and MichaelHirn committed Nov 25, 2015
1 parent 64c23db commit f5fd023
Show file tree
Hide file tree
Showing 45 changed files with 2,805 additions and 1,510 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ license = "MIT"

[dependencies]
libc = "0.2"
bitflags = "0.3"
rblas = "0.0.10"
enum_primitive = "0.1.0"
byteorder = "0.4"
num = "0.1"
clippy = "0.0.23"

Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
Collenchyma is a framework for fast, parallel and hardware-agnostic computation,
similar to [Arrayfire][arrayfire].

Collenchyma comes with a super simple API, which allows you to write code once
and then execute it on one or multiple devices (CPUs, GPUs) without the need to
care for the specific computation language (OpenCL, CUDA, native CPU) or the
underlying hardware.

Collenchyma was started at [Autumn][autumn] to support fast and parallel
computations, at the Machine Intelligence Framework [Leaf][leaf], on various
backends such as OpenCL, CUDA, or native CPU.
Collenchyma is written in Rust, which allows for a modular and easily extensible
architecture and has no hard dependency on any drivers or libraries, which makes
it easy to use, as it removes long and painful build processes.

Collenchyma comes with a super simple API, which allows you to write code once
and then execute it on one or multiple devices (CPUs, GPUs) without the need to
care for the specific computation language (OpenCL, CUDA, native CPU) or the
underlying hardware.

For more information,

* see Collenchyma's [Documentation](http://autumnai.github.io/collenchyma)
Expand Down
129 changes: 58 additions & 71 deletions src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! This is the abstraction over which you are interacting with your devices. You can create a
//! backend for computation by first choosing a specifc [Framework][frameworks] such as OpenCL and
//! afterwards selecting one or many devices to create a backend.
//! afterwards selecting one or many available hardwares to create a backend.
//!
//! A backend provides you with the functionality of managing the memory of the devices and copying
//! your objects from host to devices and the other way around. Additionally you can execute
Expand All @@ -22,101 +22,88 @@
//!
//! ```
//! extern crate collenchyma as co;
//! use co::framework::{IFramework};
//! use co::backend::*;
//! use co::frameworks::host::Host;
//! use co::framework::*;
//! use co::backend::{Backend, BackendConfig};
//! use co::frameworks::OpenCL;
//! fn main() {
//! let backend = Backend::<Host, SingleDevice>::new(Host, Host::load_devices(), SingleDevice);
//! // Initialize a new Framewok.
//! let framework = OpenCL::new();
//! // After initialization, the available hardware through the Framework can be obtained.
//! let hardwares = framework.hardwares();
//! // Create a Backend configuration with
//! // - a Framework and
//! // - the available hardwares you would like to use for computation (turn into a device).
//! let backend_config = BackendConfig::new(framework, hardwares);
//! // Create a ready to go backend from the configuration.
//! let backend = Backend::new(backend_config);
//! }
//! ```

use framework::{IFramework, FrameworkError};
use frameworks::Host;
use device::Device;

#[derive(Debug, Copy, Clone)]
/// Defines a single device backend.
pub struct SingleDevice;
#[derive(Debug, Copy, Clone)]
/// Defines a multi device backend.
pub struct MultiDevice;

/// Defines the parent backend type.
pub trait IBackendType { }
/// Defines the single backend type.
pub trait ISingleDevice { }
/// Defines the multi backend type.
pub trait IMultiDevice { }

impl IBackendType for SingleDevice { }
impl ISingleDevice for SingleDevice { }

impl IBackendType for MultiDevice { }
impl IMultiDevice for MultiDevice { }
use device::IDevice;

#[derive(Debug, Clone)]
/// Defines the main and highest struct of Collenchyma.
pub struct Backend<F: IFramework, T: IBackendType> {
pub struct Backend<F: IFramework> {
/// Provides the Framework.
///
/// The Framework implementation such as OpenCL, CUDA, etc. defines, which should be used and
/// determines which devices will be available and how parallel kernel functions can be
/// determines which hardwares will be available and how parallel kernel functions can be
/// executed.
///
/// Default: [Host][host]
/// Default: [Native][native]
///
/// [host]: ../frameworks/host/index.html
/// [native]: ../frameworks/native/index.html
framework: Box<F>,
/// Provides all the devices that are available through the Framework.
devices: Vec<Device>,
backend_type: T,
/// Provides a device, created from one or many hardwares, which are ready to execute kernel
/// methods and synchronize memory.
device: F::D,
}

/// Defines the functionality of the Backend.
impl<F: IFramework + Clone, T: IBackendType> Backend<F, T> {

/// Initialize a new Backend with a specific Framework
///
/// Loads all the available devices through the Framework
pub fn new(framework: F, devices: Vec<Device>, b_type: T) -> Backend<F, T> {
if devices.len() > 1 {
Backend {
framework: Box::new(framework.clone()),
devices: devices,
backend_type: b_type,
}
} else {
Backend {
framework: Box::new(framework.clone()),
devices: devices,
backend_type: b_type,
}
impl<F: IFramework + Clone> Backend<F> {
/// Initialize a new Backend from a BackendConfig.
pub fn new(config: BackendConfig<F>) -> Result<Backend<F>, FrameworkError> {
match config.framework.new_device(config.hardwares) {
Ok(device) => Ok(Backend {
framework: Box::new(config.framework),
device: device,
}),
Err(err) => Err(err),
}
}
}

impl<F: IFramework, T: ISingleDevice> Backend<F, T> {
/// Returns the available hardware.
pub fn hardwares(&self) -> Vec<F::H> {
self.framework.hardwares()
}

/// Executes a kernel on the backend.
///
/// This is the main function of the Collenchyma. It takes care of syncing the memory to the
/// backend device, where the operation will be executed, executes the operation in parallel if
/// so desired and returns the result.
pub fn call() -> i32 {
unimplemented!()
/// Returns the backend framework.
pub fn framework(&self) -> Box<F> {
self.framework.clone()
}

/// Returns the backend device.
pub fn device(&self) -> F::D {
self.device.clone()
}
}

impl<F, T> Backend<F, T>
where F: IFramework,
T: IMultiDevice {
#[derive(Debug, Clone)]
/// Provides Backend Configuration.
///
/// Use it to initialize a new Backend.
pub struct BackendConfig<F: IFramework> {
framework: F,
hardwares: Vec<F::H>,
}

/// Executes a kernel on the backend.
///
/// This is the main function of the Collenchyma. It takes care of syncing the memory to the
/// backend device, where the operation will be executed, executes the operation in parallel if
/// so desired and returns the result.
pub fn call() -> i32 {
unimplemented!()
impl<F: IFramework + Clone> BackendConfig<F> {
/// Creates a new BackendConfig.
pub fn new(framework: F, hardwares: Vec<F::H>) -> BackendConfig<F> {
BackendConfig {
framework: framework.clone(),
hardwares: hardwares,
}
}
}
22 changes: 18 additions & 4 deletions src/program.rs → src/binary.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Provides the generic functionality for a collection of backend-agnostic operations.
//!
//! A program defines one or usually many kernel functions, sharing related functionalities.
//! A binary defines one or usually many operations, sharing related functionalities.
//! Two examples would be [BLAS][blas] (Basic Linear Algebra Subprograms) or [cuDNN][cudnn],
//! providing operations for specific applications.
//! The difference between these programs and programs defined in Collenchyma is, that a program in
Expand Down Expand Up @@ -35,7 +35,7 @@
//!
//! The specific programs (BLAS, DNN, etc.) implement the shared functionality for all
//! or some of the supported [frameworks][frameworks]. This is done as the program provides traits
//! which, then cab be implemented for each of specific framework. This generates a nice, native
//! which, then can be implemented for each specific framework. This generates a nice, native
//! Rust access to these kernel methods, with a unified interface for every backend and completely
//! controllable at runtime.
//!
Expand All @@ -51,5 +51,19 @@
//! [backend-call]: ../backend/struct.Backend.html#method.call
//! [kernel]: ../kernel/index.html

/// Defines the functionality that a Program implementation needs to support
pub trait Program {}
use operation::IOperation;
use library::ILibrary;
use std::collections::HashMap;

/// Defines the functionality for turning a library into backend-specific, executable operations.
pub trait IBinary {
/// The Operation representation for this Binary.
type O: IOperation;
/// The Library representation for this Binary.
type L: ILibrary;
/// Returns the unique identifier of the Binary.
fn id(&self) -> isize;
/// Creates a HashMap of available, ready-to-use operations, based on the provided library and
/// tailored for a framework.
fn create_operations() -> HashMap<String, Self::O>;
}
24 changes: 0 additions & 24 deletions src/buffer.rs

This file was deleted.

Loading

0 comments on commit f5fd023

Please sign in to comment.