|
|
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
|