diff --git a/Cargo.lock b/Cargo.lock index 05e622fb1..d27328f22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,6 +244,15 @@ dependencies = [ "term 0.5.2", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "coaster" version = "0.1.0" @@ -1854,6 +1863,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +[[package]] +name = "smallvec" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" + [[package]] name = "socket2" version = "0.3.11" diff --git a/coaster-nn/src/frameworks/cuda/mod.rs b/coaster-nn/src/frameworks/cuda/mod.rs index 8cecd6089..dd92a30b3 100644 --- a/coaster-nn/src/frameworks/cuda/mod.rs +++ b/coaster-nn/src/frameworks/cuda/mod.rs @@ -801,7 +801,7 @@ impl Rnn for Backend where T: Float + DataTypeInfo { sequence_length: i32, batch_size: i32, input_size: i32 - ) -> Result, Error> { + ) -> Result>, Error> { let mut x_desc: Vec = Vec::with_capacity(sequence_length as usize); let data_type = ::cudnn_data_type(); @@ -826,7 +826,7 @@ impl Rnn for Backend where T: Float + DataTypeInfo { }?; // TODO: Update for different sizing let dim_w: Vec = vec![weight_size / 4, 1, 1]; - Ok(dim_w) + Ok(vec![dim_w]) } fn new_rnn_config( @@ -909,7 +909,7 @@ impl Rnn for Backend where T: Float + DataTypeInfo { src: &SharedTensor, output: &mut SharedTensor, rnn_config: &Self::CRNN, - weight: &SharedTensor, + weights: &[&SharedTensor], workspace: &mut SharedTensor, ) -> Result<(), Error> { let src_dimensions = src.desc().clone(); @@ -922,6 +922,7 @@ impl Rnn for Backend where T: Float + DataTypeInfo { ::cudnn_data_type(), )?; + let weight = weights[0]; let weight_desc = weight.cudnn_filter_desc()?; let reserve = rnn_config.training_reserve(); @@ -960,7 +961,7 @@ impl Rnn for Backend where T: Float + DataTypeInfo { output: &SharedTensor, output_gradient: &SharedTensor, rnn_config: &Self::CRNN, - weight: &SharedTensor, + weights: &[&SharedTensor], workspace: &mut SharedTensor) -> Result<(), Error> { let src_dimensions = src.desc().clone(); @@ -972,6 +973,8 @@ impl Rnn for Backend where T: Float + DataTypeInfo { rnn_config.num_layers, ::cudnn_data_type(), )?; + + let weight = weights[0]; let weight_desc = weight.cudnn_filter_desc()?; let _src_mem = read!(src, self); @@ -1017,7 +1020,7 @@ impl Rnn for Backend where T: Float + DataTypeInfo { fn rnn_backward_weights(&self, src: &SharedTensor, output: &SharedTensor, - filter: &mut SharedTensor, + weight_gradients: &mut [&mut SharedTensor], rnn_config: &Self::CRNN, workspace: &mut SharedTensor) -> Result<(), Error> { @@ -1030,6 +1033,8 @@ impl Rnn for Backend where T: Float + DataTypeInfo { rnn_config.num_layers, ::cudnn_data_type(), )?; + + let filter = &mut weight_gradients[0]; let filter_desc = filter.cudnn_filter_desc()?; let src_mem = read!(src, self); let output_mem = read!(output, self); diff --git a/coaster-nn/src/frameworks/native/mod.rs b/coaster-nn/src/frameworks/native/mod.rs index 28b524f39..3b67cb0c5 100644 --- a/coaster-nn/src/frameworks/native/mod.rs +++ b/coaster-nn/src/frameworks/native/mod.rs @@ -7,6 +7,7 @@ use std::cmp::PartialOrd; use std::fmt::Debug; use std::ops::*; +use std::time::SystemTime; use rand::{Rng, SeedableRng}; use rand_hc as hc128; @@ -75,6 +76,12 @@ fn map2(src1: &[T], src2: &[T], dst: &mut [T], f: F) -> Result<(), Error> Ok(()) } +fn get_random_seed() -> Result { + let start = SystemTime::now(); + let time = start.duration_since(SystemTime::UNIX_EPOCH)?; + Ok(time.as_millis() as u64) +} + impl NN for Backend where T: Add + Mul + Default + Copy @@ -833,9 +840,29 @@ impl Pooling for Backend impl Rnn for Backend where T: Float + Default + Copy + PartialOrd + Bounded { - fn new_rnn_config(&self, src: &SharedTensor, dropout_probability: Option, dropout_seed: Option, sequence_length: i32, network_mode: RnnNetworkMode, input_mode: RnnInputMode, direction_mode: DirectionMode, algorithm: RnnAlgorithm, hidden_size: i32, num_layers: i32, batch_size: i32) -> Result { - // TODO: Implement Config to hold parameters regarding the RNN - unimplemented!() + fn new_rnn_config(&self, + src: &SharedTensor, + dropout_probability: Option, + dropout_seed: Option, + sequence_length: i32, + network_mode: RnnNetworkMode, + input_mode: RnnInputMode, + direction_mode: DirectionMode, + algorithm: RnnAlgorithm, + hidden_size: i32, + num_layers: i32, + batch_size: i32 + ) -> Result { + let config = Self::CRNN { + hidden_size: hidden_size as usize, + num_layers: num_layers as usize, + dropout_probability: dropout_probability.unwrap_or(0.1f32), + dropout_seed: dropout_seed.unwrap_or(0), + direction_mode, + input_mode, + rnn_type: network_mode, + }; + Ok(config) } fn generate_rnn_weight_description( @@ -844,9 +871,14 @@ impl Rnn for Backend sequence_length: i32, batch_size: i32, input_size: i32, - ) -> Result, Error> { + ) -> Result>, Error> { // This will end up being the tensor descriptor for the weights associated with the RNN pass - unimplemented!() + match rnn_config.rnn_type { + RnnNetworkMode::ReLU => { + unimplemented!(); + } + _ => unimplemented!() + } } fn rnn_forward( @@ -854,11 +886,18 @@ impl Rnn for Backend src: &SharedTensor, output: &mut SharedTensor, rnn_config: &Self::CRNN, - weight: &SharedTensor, + weights: &[&SharedTensor], workspace: &mut SharedTensor, ) -> Result<(), Error> { // TODO: Implement RNN Forward Pass - unimplemented!() + + match rnn_config.rnn_type { + RnnNetworkMode::ReLU => { + + }, + _ => unimplemented!(), + }; + Ok(()) } fn rnn_backward_data(&self, @@ -867,7 +906,7 @@ impl Rnn for Backend output: &SharedTensor, output_gradient: &SharedTensor, rnn_config: &Self::CRNN, - weight: &SharedTensor, + weights: &[&SharedTensor], workspace: &mut SharedTensor) -> Result<(), Error> { // TODO: Implement Backward Pass for RNN for the Input @@ -877,7 +916,7 @@ impl Rnn for Backend fn rnn_backward_weights(&self, src: &SharedTensor, output: &SharedTensor, - filter: &mut SharedTensor, + weight_gradients: &mut [&mut SharedTensor], rnn_config: &Self::CRNN, workspace: &mut SharedTensor) -> Result<(), Error> { diff --git a/coaster-nn/src/plugin.rs b/coaster-nn/src/plugin.rs index 787558b08..7118f8131 100644 --- a/coaster-nn/src/plugin.rs +++ b/coaster-nn/src/plugin.rs @@ -304,7 +304,7 @@ pub trait Rnn: NN { sequence_length: i32, batch_size: i32, input_size: i32, - ) -> Result, crate::co::error::Error>; + ) -> Result>, crate::co::error::Error>; /// Train a LSTM Network and Return Results // TODO: Create alternate rnn_forward or alternate path to work with pretrained networks @@ -315,26 +315,28 @@ pub trait Rnn: NN { src: &SharedTensor, output: &mut SharedTensor, rnn_config: &Self::CRNN, - weight: &SharedTensor, + weights: &[&SharedTensor], workspace: &mut SharedTensor, ) -> Result<(), crate::co::error::Error>; /// Calculates RNN Gradients for Input/Hidden/Cell + /// Compute Gradient of Input w.r.t. Output fn rnn_backward_data(&self, src: &SharedTensor, src_gradient: &mut SharedTensor, output: &SharedTensor, output_gradient: &SharedTensor, rnn_config: &Self::CRNN, - weight: &SharedTensor, + weights: &[&SharedTensor], workspace: &mut SharedTensor) -> Result<(), crate::co::error::Error>; /// Calculates RNN Gradients for Weights + /// Compute Gradient of Weights w.r.t. Output fn rnn_backward_weights(&self, src: &SharedTensor, output: &SharedTensor, - filter: &mut SharedTensor, + weight_gradients: &mut [&mut SharedTensor], rnn_config: &Self::CRNN, workspace: &mut SharedTensor) -> Result<(), crate::co::error::Error>; diff --git a/coaster/src/device.rs b/coaster/src/device.rs index efed95d1f..b71b1760a 100644 --- a/coaster/src/device.rs +++ b/coaster/src/device.rs @@ -48,7 +48,7 @@ pub trait MemorySync { -> Result<(), Error>; } -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] /// Defines a generic set of Memory Errors. pub enum Error { /// No route found for memory transfer between devices @@ -57,6 +57,8 @@ pub enum Error { MemorySyncError, /// Framework error at memory allocation. MemoryAllocationError, + /// Generic System error + SystemError(String), /// Failures related to the Native framework implementation. #[cfg(feature = "native")] @@ -71,17 +73,18 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let msg = match *self { - Error::NoMemorySyncRoute => "No available memory synchronization route".to_string(), - Error::MemorySyncError => "Memory synchronization failed".to_string(), - Error::MemoryAllocationError => "Memory allocation failed".to_string(), + let msg = match &self { + &Error::NoMemorySyncRoute => "No available memory synchronization route".to_string(), + &Error::MemorySyncError => "Memory synchronization failed".to_string(), + &Error::MemoryAllocationError => "Memory allocation failed".to_string(), + &Error::SystemError(s) => s.clone(), #[cfg(feature = "native")] - Error::Native(ref err) => format!("Native error: {}", err.to_string()), + &Error::Native(ref err) => format!("Native error: {}", err.to_string()), #[cfg(feature = "opencl")] - Error::OpenCL(ref err) => format!("OpenCL error: {}", err.to_string()), + &Error::OpenCL(ref err) => format!("OpenCL error: {}", err.to_string()), #[cfg(feature = "cuda")] - Error::Cuda(ref err) => format!("Cuda error: {}", err.to_string()) + &Error::Cuda(ref err) => format!("Cuda error: {}", err.to_string()) }; write!(f, "{}", msg) @@ -91,16 +94,15 @@ impl fmt::Display for Error { impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { - Error::NoMemorySyncRoute => None, - Error::MemorySyncError => None, - Error::MemoryAllocationError => None, - #[cfg(feature = "native")] Error::Native(ref err) => Some(err), #[cfg(feature = "opencl")] Error::OpenCL(ref err) => Some(err), #[cfg(feature = "cuda")] Error::Cuda(ref err) => Some(err), + + // catch-all + _ => None } } } diff --git a/coaster/src/error.rs b/coaster/src/error.rs index cc914097b..3659978f1 100644 --- a/coaster/src/error.rs +++ b/coaster/src/error.rs @@ -1,6 +1,7 @@ //! Defines the general set of error types in Coaster. use std::{error, fmt}; +use std::fmt::Display; #[derive(Debug)] /// Defines the set of available Coaster error types. @@ -15,7 +16,7 @@ pub enum Error { Device(crate::device::Error), } -impl fmt::Display for Error { +impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::Framework(ref err) => write!(f, "Framwork error: {}", err), @@ -36,3 +37,9 @@ impl error::Error for Error { } } } + +impl From for Error { + fn from(time_err: std::time::SystemTimeError) -> Self { + Error::Device(crate::device::Error::SystemError(format!("{:?}", time_err))) + } +} diff --git a/coaster/src/plugin.rs b/coaster/src/plugin.rs index 2df39a778..f863266a3 100644 --- a/coaster/src/plugin.rs +++ b/coaster/src/plugin.rs @@ -37,7 +37,7 @@ pub mod numeric_helpers { pub use num::traits::*; } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] /// Defines a high-level Plugin Error. pub enum Error { /// Failure related to `SharedTensor`: use of uninitialized memory, diff --git a/coaster/src/tensor.rs b/coaster/src/tensor.rs index 0c787c04e..3393d53fe 100644 --- a/coaster/src/tensor.rs +++ b/coaster/src/tensor.rs @@ -525,7 +525,7 @@ impl SharedTensor { } /// Errors than can occur when synchronizing memory. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Error { /// Error caused by operations with device: allocation, memory synchronization, etc. DeviceError(DeviceError), diff --git a/juice/src/layers/common/rnn.rs b/juice/src/layers/common/rnn.rs index d88afad5e..f3d2d45ae 100644 --- a/juice/src/layers/common/rnn.rs +++ b/juice/src/layers/common/rnn.rs @@ -37,14 +37,15 @@ //! | NVIDIA GeForce GTX 1070 | use std::rc::Rc; +use std::fmt::Debug; use std::sync::{Arc, RwLock}; use conn::{DirectionMode, RnnAlgorithm, RnnInputMode, RnnNetworkMode}; +use conn::RnnConfig as ConnRnnConfig; use crate::capnp_util::*; use crate::co::prelude::*; use crate::conn; -use crate::conn::RnnConfig as connRnnConfig; use crate::juice_capnp::rnn_config as capnp_config; use crate::layer::*; use crate::util::ArcLock; @@ -52,7 +53,7 @@ use crate::weight::FillerType; #[derive(Debug, Clone)] /// -pub struct Rnn> { +pub struct Rnn { hidden_size: usize, num_layers: usize, dropout_probability: f32, @@ -61,12 +62,12 @@ pub struct Rnn> { input_mode: RnnInputMode, direction_mode: DirectionMode, workspace: Option>>, - rnn_config: Option>, + rnn_config: Option>, } -impl> Rnn { +impl Rnn { /// Create a RNN from a RNNConfig - pub fn from_config(config: &RnnConfig) -> Rnn { + pub fn from_config(config: &RnnConfig) -> Rnn { Rnn { hidden_size: config.hidden_size, num_layers: config.num_layers, @@ -81,7 +82,8 @@ impl> Rnn { } } -impl> ILayer for Rnn { +/// Cuda Implementation of methods +impl> ILayer for Rnn { impl_ilayer_common!(); fn auto_weight_blobs(&self) -> bool { @@ -136,12 +138,13 @@ impl> ILayer for Rnn { ) .unwrap(); - let filter_dimensions: TensorDesc = backend.generate_rnn_weight_description( + let fil_dims = backend.generate_rnn_weight_description( &config, sequence_length as i32, batch_size as i32, input_size as i32, ).unwrap(); + let filter_dimensions: TensorDesc = fil_dims.get(0).unwrap().to_owned(); weights_data[0].write().unwrap().resize(&filter_dimensions).unwrap(); weights_data[1].write().unwrap().resize(&(1, self.hidden_size)).unwrap(); @@ -165,7 +168,7 @@ impl> ILayer for Rnn { backend: Rc, workspace: Option>>, ) -> Option>> { - let required_size = self.rnn_config.as_ref().unwrap().workspace_size(); + let required_size = self.rnn_config.clone().unwrap().workspace_size(); let new_workspace = if workspace.is_none() { Arc::new(RwLock::new(SharedTensor::::new(&[required_size]))) } else { @@ -183,7 +186,7 @@ impl> ILayer for Rnn { } } -impl> ComputeOutput for Rnn { +impl> ComputeOutput for Rnn { fn compute_output( &self, backend: &B, @@ -195,12 +198,12 @@ impl> ComputeOutput for Rnn { let rnn_config = self.rnn_config.as_ref().unwrap(); let mut workspace = self.workspace.as_ref().unwrap().write().unwrap(); backend - .rnn_forward(input_data[0], output_data[0], rnn_config, weights[0], &mut workspace) + .rnn_forward(input_data[0], output_data[0], rnn_config, weights, &mut workspace) .unwrap(); } } -impl> ComputeInputGradient for Rnn { +impl> ComputeInputGradient for Rnn { fn compute_input_gradient( &self, backend: &B, @@ -219,14 +222,14 @@ impl> ComputeInputGradient for Rnn { &output_data[0], output_gradients[0], rnn_config, - weights_data[0], + weights_data, &mut workspace, ) .unwrap(); } } -impl> ComputeParametersGradient for Rnn { +impl> ComputeParametersGradient for Rnn { fn compute_parameters_gradient( &self, backend: &B, @@ -240,13 +243,7 @@ impl> ComputeParametersGradient for Rnn backend.rnn_backward_weights(&input_data[0], &output_data[0], - &mut parameters_gradients[0], - rnn_config, - &mut workspace) - .unwrap(); - backend.rnn_backward_weights(&input_data[0], - &output_data[0], - &mut parameters_gradients[1], + parameters_gradients, rnn_config, &mut workspace) .unwrap();