use std::fmt::Debug;
use lazy_static::lazy_static;
use rand::Rng;
use nncombinator::arr::{Arr, Arr2, SerializedVec};
use nncombinator::device::input::DeviceInput;
use nncombinator::layer::{BackwardAll, BatchBackward, BatchDataType, BatchForward, BatchLoss, BatchPreTrain, ContinueForward, ForwardAll, Loss, OnStep, PartialForward, PersistProgress, PreTrain, Step, UpdateWeight};
use nncombinator::ope::UnitValue;
use nncombinator::cuda::allocator::{CudaAllocator, DeviceAlloc, MemoryPoolAllocator, MemoryPoolAllocatorInstantiation};
use nncombinator::cuda::{AsCudaMutPtr, AsCudaView, CudaMutPtr, CudaTensor1dPtr, CudaTensor2dPtr, CudaVec, WriteMemory};
use nncombinator::persistence::{Specialized, TextFilePersistence};
lazy_static! {
pub static ref SHARED_MEMORY_POOL:MemoryPoolAllocator<DeviceAlloc> = MemoryPoolAllocator::with_size(8 * 1024 * 1024 * 1024,DeviceAlloc).unwrap();
}
pub fn assert_device<U,I,D: DeviceInput<U,I>>(_:&D)
where U: UnitValue<U>,
I: BatchDataType + Debug + 'static,
<I as BatchDataType>::Type: Debug + 'static {
}
pub fn assert_forward_all<T: ForwardAll>(_:&T) {
}
pub fn assert_pre_train<U: UnitValue<U>,T: PreTrain<U>>(_:&T) {
}
pub fn assert_backward_all<U: UnitValue<U>,T: BackwardAll<U>>(_:&T) {
}
pub fn assert_loss<U: UnitValue<U>,T: Loss<U>>(_:&T) {
}
pub fn assert_update_weight<U: UnitValue<U>,T: UpdateWeight<U>>(_:&T) {
}
pub fn assert_partial_forward<T: PartialForward>(_:&T) {}
pub fn assert_continue_forward<T: ContinueForward>(_:&T) {}
pub fn assert_batch_forward<T: BatchForward>(_:&T) {
}
pub fn assert_batch_pre_train<U: UnitValue<U>,T: BatchPreTrain<U>>(_:&T) {
}
pub fn assert_batch_backward<U: UnitValue<U>,T: BatchBackward<U>>(_:&T) {
}
pub fn assert_batch_loss<U: UnitValue<U>,T: BatchLoss<U>>(_:&T) {
}
pub fn assert_step<T: Step>(_:&T) {
}
pub fn assert_on_step<T: OnStep>(_:&T) {
}
pub fn assert_text_persist_progress<T: PersistProgress<TextFilePersistence,Specialized>>(_:&T) {}
const NI: usize = 500;
const NO: usize = 600;
const BATCH: usize = 400;
pub fn gen_inputs() -> (Arr<f32,NO>,Arr2<f32,NI,NO>,SerializedVec<f32,Arr<f32,NI>>) {
let mut rng = rand::thread_rng();
let mut bias = Arr::<f32,NO>::new();
for b in bias.iter_mut() { *b = rng.gen::<f32>() * 1e-3; }
let mut units = Arr2::<f32,NI,NO>::new();
for i in 0..NI {
for j in 0..NO { units[(i,j)] = rng.gen::<f32>(); }
}
let mut inputs_host: Vec<Arr<f32,NI>> = Vec::with_capacity(BATCH);
for _ in 0..BATCH {
let mut v = Arr::<f32,NI>::new();
for x in v.iter_mut() { *x = rng.gen::<f32>(); }
inputs_host.push(v);
}
(bias,units,inputs_host.into())
}
pub fn approx_eq_slice(a: &[f32],b: &[f32],eps: f32) {
assert_eq!(a.len(),b.len());
for (i,(x,y)) in a.iter().zip(b.iter()).enumerate() {
let d = (*x - *y).abs();
assert!(d < eps,"diff[{}] = {} exceeds eps {} (x={},y={})",i,d,eps,x,y);
}
}
pub fn upload_inputs_to_device<A: MemoryPoolAllocatorInstantiation<DeviceAlloc> + CudaAllocator>(
alloc: &A,
bias: &Arr<f32,NO>,units: &Arr2<f32,NI,NO>,
batch_inputs: &SerializedVec<f32,Arr<f32,NI>>)
-> (CudaTensor1dPtr<f32,A,NO>,CudaTensor2dPtr<f32,A,NI,NO>,CudaVec<f32,CudaTensor1dPtr<f32,A,NI>,A>)
where CudaTensor1dPtr<f32,A,NO>: WriteMemory<f32>,
CudaTensor2dPtr<f32,A,NI,NO>: WriteMemory<f32>,
CudaVec<f32,CudaTensor1dPtr<f32,A,NI>,A>: AsCudaMutPtr<Pointee=f32,Allocator=A>,
for<'a> CudaMutPtr<'a,f32,A>: WriteMemory<f32>,
for<'a> &'a CudaVec<f32,CudaTensor1dPtr<f32,A,NI>,A>: AsCudaView<'a> {
let mut d_bias = CudaTensor1dPtr::<f32,A,NO>::new(alloc).unwrap();
d_bias.memcpy(bias.as_ptr(),NO).unwrap();
let mut flat_units: Vec<f32> = Vec::with_capacity(NI * NO);
for i in 0..NI { for j in 0..NO { flat_units.push(units[(i,j)]); } }
let mut d_units = CudaTensor2dPtr::<f32,A,NI,NO>::new(alloc).unwrap();
d_units.memcpy(flat_units.as_ptr(),flat_units.len()).unwrap();
let mut flat_inputs: Vec<f32> = Vec::with_capacity(BATCH * NI);
for b in batch_inputs.iter() {
for &v in b.iter() { flat_inputs.push(v); }
}
let mut d_inputs = CudaVec::<f32,CudaTensor1dPtr<f32,A,NI>,A>::new(BATCH,alloc).unwrap();
{
let mut ptr = d_inputs.as_cuda_mut_ptr();
ptr.memcpy(flat_inputs.as_ptr(),flat_inputs.len()).unwrap();
}
(d_bias,d_units,d_inputs)
}