Blame projects/neural/layer.test.inc.cpp

Ivan Mahonin e865c9
#ifndef LAYER_TEST_INC_CPP
Ivan Mahonin e865c9
#define LAYER_TEST_INC_CPP
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin b579b3
#include "test.inc.cpp"
Ivan Mahonin e4740d
#include "layer.inc.cpp"
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin b579b3
class LayerTest: public Test {
Ivan Mahonin e865c9
public:
Ivan Mahonin e865c9
  static bool testLayer(const char *name, Layer &l) {
Ivan Mahonin e865c9
    Stage st(name);
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    assert(l.next);
Ivan Mahonin e865c9
    Layer &p = l;
Ivan Mahonin e865c9
    Layer &c = *l.next;
Ivan Mahonin e865c9
    
Ivan Mahonin e865c9
    
Ivan Mahonin e4740d
    class H: public ThreadControl {
Ivan Mahonin e4740d
    public:
Ivan Mahonin e865c9
      Layer &p;
Ivan Mahonin e865c9
      Layer &c;
Ivan Mahonin e865c9
Ivan Mahonin e4740d
      H(Layer &p, Layer &c): p(p), c(c) { }
Ivan Mahonin e865c9
  
Ivan Mahonin 15c502
      void fillLayout(Layout l, Neuron *neurons) {
Ivan Mahonin 15c502
        for(int y = 0; y < l.sy; ++y)
Ivan Mahonin 15c502
        for(int x = 0; x < l.sx; ++x)
Ivan Mahonin 15c502
        for(int z = 0; z < l.sz; ++z) {
Ivan Mahonin 15c502
          Neuron &n = neurons[ (y*l.sx + x)*l.sz + z ];
Ivan Mahonin 15c502
          n = Neuron{};
Ivan Mahonin 15c502
          if ( x >= l.x0 && x < l.x1
Ivan Mahonin 15c502
            && y >= l.y0 && y < l.y1
Ivan Mahonin 15c502
            && z >= l.z0 && z < l.z1 )
Ivan Mahonin 15c502
          {
Ivan Mahonin 15c502
            n.v = rand()/(NeuronReal)RAND_MAX;
Ivan Mahonin 15c502
            n.d = rand()/(NeuronReal)RAND_MAX;
Ivan Mahonin 15c502
          }
Ivan Mahonin 15c502
        }
Ivan Mahonin 15c502
      }
Ivan Mahonin 15c502
  
Ivan Mahonin e865c9
      void prepareData() {
Ivan Mahonin e865c9
        memcpy(c.neurons, c_neurons.data(), c.neuronsCount*sizeof(Neuron));
Ivan Mahonin e865c9
        memcpy(p.neurons, p_neurons.data(), p.neuronsCount*sizeof(Neuron));
Ivan Mahonin 15c502
        if (c.weightsCount)
Ivan Mahonin 15c502
          memcpy(c.weights, weights.data(), c.weightsCount*sizeof(Weight));
Ivan Mahonin e865c9
      }
Ivan Mahonin e865c9
  
Ivan Mahonin e865c9
      void applyDelta() {
Ivan Mahonin e865c9
        for(int i = 0; i < c.neuronsCount; ++i)
Ivan Mahonin e865c9
          c.neurons[i].d *= c_neurons[i].v - c.neurons[i].v;
Ivan Mahonin e865c9
      }
Ivan Mahonin e865c9
  
Ivan Mahonin e4740d
      void threadFunc(Barrier &barrier) override {
Ivan Mahonin e865c9
        c.pass(barrier);
Ivan Mahonin e865c9
        barrier.wait();
Ivan Mahonin e4740d
        if (!barrier.tid) applyDelta();
Ivan Mahonin e865c9
        barrier.wait();
Ivan Mahonin e865c9
        c.backpassDeltas(barrier);
Ivan Mahonin e865c9
        barrier.wait();
Ivan Mahonin e865c9
        c.backpassWeights(barrier);
Ivan Mahonin e865c9
      }
Ivan Mahonin e865c9
      
Ivan Mahonin e865c9
      bool test(const char *name, int threadsCount) {
Ivan Mahonin e865c9
        Stage st(name);
Ivan Mahonin e865c9
        
Ivan Mahonin e865c9
        assert(threadsCount > 0);
Ivan Mahonin e865c9
        
Ivan Mahonin e865c9
        prepareData();
Ivan Mahonin e865c9
Ivan Mahonin e865c9
        p.split(threadsCount);
Ivan Mahonin e865c9
        c.split(threadsCount);
Ivan Mahonin e4740d
        runThreads(threadsCount);
Ivan Mahonin e865c9
        
Ivan Mahonin e865c9
        for(int i = 0; i < c.neuronsCount; ++i) {
Ivan Mahonin e865c9
          NeuronReal a = c.neurons[i].v;
Ivan Mahonin e865c9
          NeuronReal b = c_neurons[i + c.neuronsCount].v;
Ivan Mahonin e865c9
          if (fabs(a - b) > 1e-6)
Ivan Mahonin e865c9
            { printf("results differs at neuron %d, was %g, expected %g\n", i, a, b); ++errors; break; }
Ivan Mahonin e865c9
        }
Ivan Mahonin e865c9
        
Ivan Mahonin e865c9
        for(int i = 0; i < p.neuronsCount; ++i) {
Ivan Mahonin e865c9
          NeuronReal a = p.neurons[i].d;
Ivan Mahonin e865c9
          NeuronReal b = p_neurons[i + p.neuronsCount].d;
Ivan Mahonin e865c9
          if (fabs(a - b) > 1e-6)
Ivan Mahonin e865c9
            { printf("deltas differs at neuron %d, was %g, expected %g\n", i, a, b); ++errors; break; }
Ivan Mahonin e865c9
        }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
        for(int i = 0; i < c.weightsCount; ++i) {
Ivan Mahonin e865c9
          WeightReal a = c.weights[i].w;
Ivan Mahonin e865c9
          WeightReal b = weights[i + c.weightsCount].w;
Ivan Mahonin e865c9
          if (fabs(a - b) > 1e-6)
Ivan Mahonin e865c9
            { printf("weights differs at %d, was %g, expected %g\n", i, a, b); ++errors; break; }
Ivan Mahonin e865c9
        }
Ivan Mahonin e865c9
        
Ivan Mahonin e865c9
        if (!st) {
Ivan Mahonin e865c9
          p.layout.printYXZ("prev layout");
Ivan Mahonin e865c9
          c.layout.printYXZ("curr layout");
Ivan Mahonin e865c9
        }
Ivan Mahonin e865c9
        
Ivan Mahonin e865c9
        return st;
Ivan Mahonin e865c9
      }
Ivan Mahonin e865c9
    } h(p, c);
Ivan Mahonin e865c9
    
Ivan Mahonin e865c9
    // make base data
Ivan Mahonin e865c9
    
Ivan Mahonin e865c9
    init(c.neuronsCount*2, p.neuronsCount*2, c.weightsCount*2);
Ivan Mahonin 15c502
    h.fillLayout(c.layout, c_neurons.data());
Ivan Mahonin 15c502
    h.fillLayout(p.layout, p_neurons.data());
Ivan Mahonin 15c502
    if (c.weightsCount)
Ivan Mahonin 15c502
      memcpy(weights.data(), c.weights, c.weightsCount*sizeof(Weight));
Ivan Mahonin e865c9
    
Ivan Mahonin e865c9
    h.prepareData();
Ivan Mahonin e865c9
    c.testPass();
Ivan Mahonin e865c9
    h.applyDelta();
Ivan Mahonin e865c9
    c.testBackpass();
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    memcpy(&c_neurons[c.neuronsCount], c.neurons, c.neuronsCount*sizeof(Neuron));
Ivan Mahonin e865c9
    memcpy(&p_neurons[p.neuronsCount], p.neurons, p.neuronsCount*sizeof(Neuron));
Ivan Mahonin 15c502
    if (c.weightsCount)
Ivan Mahonin 15c502
      memcpy(&weights[c.weightsCount], c.weights, c.weightsCount*sizeof(Weight));
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    h.test("single-thread", 1);
Ivan Mahonin e865c9
    h.test("2-threads", 2);
Ivan Mahonin e865c9
    h.test("7-threads", 7);
Ivan Mahonin e865c9
    h.test("8-threads", 8);
Ivan Mahonin e865c9
    //h.test("512-threads", 512);
Ivan Mahonin e865c9
    
Ivan Mahonin e865c9
    return st;
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
};
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
#endif