Blame projects/neural/layer.inc.cpp

e865c9
#ifndef LAYER_INC_CPP
e865c9
#define LAYER_INC_CPP
e865c9
e865c9
e865c9
#include <cmath></cmath>
e865c9
#include <cstdio></cstdio>
e865c9
#include <cstdlib></cstdlib>
e865c9
#include <cstring></cstring>
e865c9
#include <cassert></cassert>
e865c9
e865c9
#include <atomic></atomic>
e865c9
#include <vector></vector>
036a8f
#include <string></string>
e865c9
#include <algorithm></algorithm>
e865c9
e865c9
e865c9
#include "layout.inc.cpp"
e865c9
e865c9
e865c9
e865c9
typedef double WeightReal;
e865c9
typedef double NeuronReal;
e865c9
typedef double AccumReal;
e865c9
e865c9
typedef int WeightInt;
e865c9
typedef int AccumInt;
e865c9
e865c9
e865c9
#define RANDOM_MAX 0x7fffffff
e865c9
inline unsigned int randomNext(unsigned int prev)
e865c9
  { return (1103515245*prev + 12345) & RANDOM_MAX; }
e865c9
e865c9
e865c9
struct Accum {
e865c9
  union { AccumReal v; AccumInt i; };
e865c9
};
e865c9
e865c9
e865c9
struct Neuron {
e865c9
  NeuronReal v, d;
e865c9
  Accum a;
e865c9
};
e865c9
e865c9
e865c9
struct Weight {
e865c9
  union { WeightReal w; WeightInt i; };
e865c9
};
e865c9
e865c9
e865c9
struct Iter {
e865c9
  typedef Accum AccumType;
e865c9
  typedef NeuronReal* DataType;
e865c9
  typedef AccumType DataAccumType;
e865c9
  static inline void init(Neuron&, AccumType&) { }
e865c9
  static inline void iter(Neuron&, Weight&, AccumType&) { }
e865c9
  static inline void done(Neuron&, AccumType&) { }
e865c9
  static inline void iter2(Neuron&, Neuron&, Weight&) { }
e865c9
  static inline void iter3(Neuron&) { }
e865c9
  static inline void iter4(Neuron&, DataType, DataAccumType&) { }
e865c9
};
e865c9
e865c9
e865c9
class Barrier {
e865c9
private:
e865c9
  std::atomic<unsigned int=""> &counter;</unsigned>
e865c9
  unsigned int next;
e865c9
public:
e865c9
  const unsigned int tid;
e865c9
  const unsigned int threads;
e865c9
e865c9
  Barrier(const Barrier&) = delete;
e865c9
  inline Barrier(std::atomic<unsigned int=""> &counter, unsigned int tid, unsigned int threads):</unsigned>
e865c9
    counter(counter), next(), tid(tid), threads(threads) { assert(tid < threads); }
e865c9
  inline void wait() { next += threads; ++counter; while(counter < next); }
e865c9
  inline void subwait() { while(counter < next + tid); }
e865c9
};
e865c9
e865c9
e865c9
struct Stat {
e865c9
  int neurons;
e865c9
  int activeNeurons;
e865c9
  int weights;
e865c9
  int links;
e865c9
  size_t memsize;
e865c9
e865c9
  Stat(): neurons(), activeNeurons(), weights(), links(), memsize() { }
e865c9
e865c9
  Stat& operator+= (const Stat &b) {
e865c9
    neurons += b.neurons;
e865c9
    activeNeurons += b.activeNeurons;
e865c9
    weights += b.weights;
e865c9
    links   += b.links;
e865c9
    memsize += b.memsize;
e865c9
    return *this;
e865c9
  }
e865c9
e865c9
  void print(const char *prefix = nullptr) const {
e865c9
    if (prefix && *prefix) printf("%s: ", prefix);
e865c9
    printf("neurons: %d / %d, links %d / %d, memSize: %llu\n", activeNeurons, neurons, weights, links, (unsigned long long)memsize);
e865c9
  }
e865c9
};
e865c9
e865c9
e865c9
class Layer {
e865c9
public:
e865c9
  Layer *prev, *next;
e865c9
e865c9
  Layout layout;
e865c9
e865c9
  Neuron *neurons;
e865c9
  int neuronsCount;
e865c9
e865c9
  Weight *weights;
e865c9
  int weightsCount;
e865c9
  bool ownWeights;
e865c9
e865c9
  const char *filename;
e865c9
e865c9
  Stat stat;
e865c9
e865c9
  Layout::List mtLayouts;
036a8f
  Layout::List mtPrevLayouts;
e865c9
e865c9
e865c9
  Layer(Layer *prev, const Layout &layout, int weightsCount = 0, Weight *weights = nullptr):
e865c9
    prev(prev ? &prev->back() : nullptr),
e865c9
    next(),
e865c9
    layout(layout),
e865c9
    neurons(),
e865c9
    neuronsCount(layout.getCount()),
e865c9
    weights(weights),
e865c9
    weightsCount(weightsCount),
e865c9
    ownWeights(!weights && weightsCount),
e865c9
    filename()
e865c9
  {
e865c9
    assert(layout);
e865c9
    assert(neuronsCount > 0);
e865c9
    assert(weightsCount >= 0);
e865c9
    assert(!prev == !weightsCount);
e865c9
e865c9
    if (this->prev) this->prev->next = this;
e865c9
    if (neuronsCount) {
e865c9
      neurons = new Neuron[neuronsCount];
e865c9
      memset(neurons, 0, sizeof(*neurons)*neuronsCount);
e865c9
    }
e865c9
    if (ownWeights) {
e865c9
      this->weights = new Weight[weightsCount];
e865c9
      memset(this->weights, 0, sizeof(*this->weights)*weightsCount);
e865c9
    }
e865c9
e865c9
    stat.neurons = neuronsCount;
e865c9
    stat.activeNeurons = layout.getActiveCount();
e865c9
    stat.weights = weightsCount;
e865c9
    stat.links = weightsCount;
e865c9
    stat.memsize = neuronsCount*sizeof(*neurons);
e865c9
    if (ownWeights) stat.memsize += weightsCount*sizeof(*weights);
e865c9
  }
e865c9
e865c9
e865c9
  virtual ~Layer() {
e865c9
    if (next) delete next;
e865c9
    if (neurons) delete[] neurons;
e865c9
    if (ownWeights) delete[] weights;
e865c9
  }
e865c9
e865c9
e865c9
  inline Layer& front()
e865c9
    { Layer *l = this; while(l->prev) l = l->prev; return *l; }
e865c9
  inline Layer& back()
e865c9
    { Layer *l = this; while(l->next) l = l->next; return *l; }
e865c9
  inline Stat sumStat() const
e865c9
    { Stat s; for(const Layer *l = this; l; l = l->next) s += l->stat; return s; }
e865c9
e865c9
  bool save() const {
e865c9
    if (filename && weightsCount) {
e865c9
      FILE *f = fopen(filename, "wb");
e865c9
      if (!f)
e865c9
        return printf("cannot open file for write: %s\n", filename), false;
e865c9
      if (!fwrite(weights, sizeof(*weights)*weightsCount, 1, f))
e865c9
        return fclose(f), printf("cannot write to file: %s\n", filename), false;
e865c9
      fclose(f);
e865c9
    }
e865c9
    return !next || next->save();
e865c9
  }
e865c9
e865c9
e865c9
  bool load() {
e865c9
    if (filename && weightsCount) {
e865c9
      FILE *f = fopen(filename, "rb");
e865c9
      if (!f)
e865c9
        return printf("cannot open file for read: %s\n", filename), false;
e865c9
      if (!fread(weights, sizeof(*weights)*weightsCount, 1, f))
e865c9
        return fclose(f), printf("cannot read from file: %s\n", filename), false;
e865c9
      fclose(f);
e865c9
    }
e865c9
    return !next || next->load();
e865c9
  }
e865c9
e865c9
  
e865c9
  void clearAccum() {
e865c9
    Accum a = {};
e865c9
    for(Neuron *in = neurons, *e = in + neuronsCount; in < e; ++in)
e865c9
      in->a = a;
e865c9
  }
e865c9
e865c9
  
e865c9
  void fillWeights(WeightReal wmin, WeightReal wmax) {
e865c9
    WeightReal k = (wmax - wmin)/RAND_MAX;
e865c9
    for(Weight *iw = weights, *e = iw + weightsCount; iw < e; ++iw)
e865c9
      iw->w = rand()*k + wmin;
e865c9
  }
e865c9
e865c9
 
036a8f
  virtual void split(int threadsCount) {
036a8f
    layout.split(mtLayouts, threadsCount);
036a8f
    if (prev) prev->layout.split(mtPrevLayouts, threadsCount);
036a8f
  }
e865c9
  virtual void pass(Barrier &barrier) { }
e865c9
  virtual void backpassWeights(Barrier &barrier) { }
e865c9
  virtual void backpassDeltas(Barrier &barrier) { }
e865c9
  
e865c9
  virtual void testPass() { }
e865c9
  virtual void testBackpass() { }
036a8f
  
036a8f
  
036a8f
  virtual void clGetThreadsData(std::vector<unsigned char=""> &data) { }</unsigned>
036a8f
  virtual void clGetPassProgram(std::string &text) { }
036a8f
  virtual void clGetBackpassWeightsProgram(std::string &text) { }
036a8f
  virtual void clGetBackpassDeltasProgram(std::string &text) { }
e865c9
};
e865c9
e865c9
e865c9
#endif