Blob Blame Raw
#ifndef COMMON_INC_CPP
#define COMMON_INC_CPP


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>

#include <atomic>
#include <vector>
#include <string>
#include <chrono>
#include <thread>
#include <algorithm>


#include "layout.inc.cpp"


typedef double WeightReal;
typedef double NeuronReal;
typedef double AccumReal;

typedef int WeightInt;
typedef int AccumInt;



#define RANDOM_MAX 0x7fffffff
inline unsigned int randomNext(unsigned int prev)
  { return (1103515245*prev + 12345) & RANDOM_MAX; }
inline unsigned int randomBranch(unsigned int seed)
  { return randomNext(seed + 1); }
  
inline void busyloop(unsigned int count)
  { while(count--) __asm__ __volatile__(""); }


inline long long timeUs() {
  static std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
  return (long long)std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::steady_clock::now() - begin ).count();
}


  
struct Accum {
  union { AccumReal v; AccumInt i; };
};


struct Neuron {
  NeuronReal v, d;
  Accum a;
};


struct Weight {
  union { WeightReal w; WeightInt i; };
};


struct Iter {
  typedef Accum AccumType;
  typedef NeuronReal* DataType;
  typedef AccumType DataAccumType;
  static inline void init(Neuron&, AccumType&) { }
  static inline void iter(Neuron&, Weight&, AccumType&) { }
  static inline void done(Neuron&, AccumType&) { }
  static inline void iter2(Neuron&, Neuron&, Weight&) { }
  static inline void iter3(Neuron&) { }
  static inline void iter4(Neuron&, DataType, DataAccumType&) { }
};



class Barrier {
private:
  std::atomic<unsigned int> &counter;
  unsigned int next;
  unsigned int busyseed;
public:
  const unsigned int tid;
  const unsigned int threads;
  unsigned int seed;

  Barrier(const Barrier&) = delete;
  inline Barrier(std::atomic<unsigned int> &counter, unsigned int tid, unsigned int threads, unsigned int seed):
    counter(counter), next(), busyseed(randomBranch(seed)), tid(tid), threads(threads), seed(seed) { assert(tid < threads); }
    
  //inline void busyloop() { }
  inline void busyloop(unsigned int maxCycles = 4096) { ::busyloop( (busyseed = randomNext(busyseed))%maxCycles ); }
  inline unsigned int rand() { return seed = randomNext(seed); }
  inline void wait() { next += threads; ++counter; while(counter < next) busyloop(); }
  inline void subwait() { while(counter < next + tid) busyloop(); }
  
};


struct Stat {
  int neurons;
  int activeNeurons;
  int weights;
  int links;
  size_t memsize;

  Stat(): neurons(), activeNeurons(), weights(), links(), memsize() { }

  Stat& operator+= (const Stat &b) {
    neurons += b.neurons;
    activeNeurons += b.activeNeurons;
    weights += b.weights;
    links   += b.links;
    memsize += b.memsize;
    return *this;
  }

  void print(const char *prefix = nullptr) const {
    if (prefix && *prefix) printf("%s: ", prefix);
    printf("neurons: %d / %d, links %d / %d, memSize: %llu\n", activeNeurons, neurons, weights, links, (unsigned long long)memsize);
  }
};


struct Quality {
  AccumReal train;
  AccumReal human;
  
  inline Quality(AccumReal train, AccumReal human): train(train), human(human) {}
  inline explicit Quality(AccumReal train = 0): Quality(train, train) {}
  inline static Quality nan() { return Quality(NAN); }
  inline static Quality bad() { return Quality(INFINITY); }
  
  inline Quality& operator+=(const Quality &b)
    { train += b.train; human += b.human; return *this; }
  inline Quality& operator*=(AccumReal x)
    { train *= x; human *= x; return *this; }
  inline bool operator<(const Quality &b) const {
    return human < b.human ? true
         : b.human < human ? false
         : train < b.train;
  }
};


struct QualityPair {
  Quality measure;
  Quality train;
  
  inline explicit QualityPair(const Quality &measure = Quality(), const Quality &train = Quality()):
    measure(measure), train(train) { }

  inline QualityPair& operator+=(const QualityPair &b)
    { measure += b.measure; train += b.train; return *this; }
  inline QualityPair& operator*=(AccumReal x)
    { measure *= x; train *= x; return *this; }
  inline bool operator<(const QualityPair &b) const {
    return measure < b.measure ? true
         : b.measure < measure ? false
         : train < b.train;
  }
};


#endif