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

Ivan Mahonin e865c9
#ifndef LAYER_CONV_TEST_INC_CPP
Ivan Mahonin e865c9
#define LAYER_CONV_TEST_INC_CPP
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
#include "layer.test.inc.cpp"
Ivan Mahonin e865c9
#include "layer.conv.inc.cpp"
Ivan Mahonin 8e5348
#include "layer.conv.shared.inc.cpp"
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin b579b3
class ConvTest: public LayerTest {
Ivan Mahonin e865c9
public:
Ivan Mahonin e865c9
  static void init(const Layout &cl, const Layout &pl, const Kernel &k, bool shared = false)
Ivan Mahonin e865c9
    { Test::init(cl.getCount(), pl.getCount(), (shared ? 1 : cl.getActiveCount())*k.sx*k.sy*pl.getD()); }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
  static bool verifyWeights(const char *name, const Layout &cl, const Layout &pl, const Kernel &k) {
Ivan Mahonin e865c9
    Stage st(name);
Ivan Mahonin e865c9
    for(int cy = cl.y0; cy < cl.y1; ++cy)
Ivan Mahonin e865c9
    for(int cx = cl.x0; cx < cl.x1; ++cx)
Ivan Mahonin e865c9
    for(int cz = cl.z0; cz < cl.z1; ++cz) {
Ivan Mahonin e865c9
      int ci = (cy*cl.sx + cx)*cl.sz + cz;
Ivan Mahonin e865c9
      for(int ky = 0; ky < k.sy; ++ky)
Ivan Mahonin e865c9
      for(int kx = 0; kx < k.sx; ++kx)
Ivan Mahonin e865c9
      for(int pz = pl.z0; pz < pl.z1; ++pz) {
Ivan Mahonin e865c9
        int wi = ((cy - cl.y0)*cl.getW() + cx - cl.x0)*cl.getD() + cz - cl.z0;
Ivan Mahonin e865c9
        wi = ((wi*k.sy + ky)*k.sx + kx)*pl.getD() + pz - pl.z0;
Ivan Mahonin e865c9
Ivan Mahonin e865c9
        int px = pl.x0 + (cx - cl.x0)*k.dx + k.ox + kx;
Ivan Mahonin e865c9
        int py = pl.y0 + (cy - cl.y0)*k.dy + k.oy + ky;
Ivan Mahonin e865c9
        if ( px < pl.x0 || px >= pl.x1
Ivan Mahonin e865c9
          || py < pl.y0 || py >= pl.y1 ) continue;
Ivan Mahonin e865c9
Ivan Mahonin e865c9
        int pi = (py*pl.sx + px)*pl.sz + pz;
Ivan Mahonin e865c9
Ivan Mahonin e865c9
        int s = (int)p_neurons.size();
Ivan Mahonin e865c9
        int w = weights[wi].i;
Ivan Mahonin e865c9
        int i = ci*s + pi + 1;
Ivan Mahonin e865c9
Ivan Mahonin e865c9
        if (w != i) {
Ivan Mahonin e865c9
          int ww = w;
Ivan Mahonin e865c9
          int wpz = ww%pl.sz; ww /= pl.sz;
Ivan Mahonin e865c9
          int wpx = ww%pl.sx; ww /= pl.sx;
Ivan Mahonin e865c9
          int wpy = ww%pl.sy; ww /= pl.sy;
Ivan Mahonin e865c9
          int wcz = ww%cl.sz; ww /= cl.sz;
Ivan Mahonin e865c9
          int wcx = ww%cl.sx; ww /= cl.sx;
Ivan Mahonin e865c9
          int wcy = ww;
Ivan Mahonin e865c9
Ivan Mahonin e865c9
          printf(
Ivan Mahonin e865c9
            "wrong index: %d = ((%d*%d + %d)*%d + %d)*%d + (%d*%d + %d)*%d + %d + 1,\n"
Ivan Mahonin e865c9
            "expected:    %d = ((%d*%d + %d)*%d + %d)*%d + (%d*%d + %d)*%d + %d + 1\n"
Ivan Mahonin e865c9
            "wi %d, ky %d, kx %d \n",
Ivan Mahonin e865c9
            w,
Ivan Mahonin e865c9
            wcy, cl.sx, wcx, cl.sz, wcz, s,
Ivan Mahonin e865c9
            wpy, pl.sx, wpx, pl.sz, wpz,
Ivan Mahonin e865c9
            i,
Ivan Mahonin e865c9
            cy, cl.sx, cx, cl.sz, cz, s,
Ivan Mahonin e865c9
            py, pl.sx, px, pl.sz, pz,
Ivan Mahonin e865c9
            wi, ky, kx );
Ivan Mahonin e865c9
          pl.printYXZ("prev layout");
Ivan Mahonin e865c9
          cl.printYXZ("curr layout");
Ivan Mahonin e865c9
          k.printYX("kernel");
Ivan Mahonin e865c9
          ++errors;
Ivan Mahonin e865c9
          return st;
Ivan Mahonin e865c9
        }
Ivan Mahonin e865c9
      }
Ivan Mahonin e865c9
    }
Ivan Mahonin e865c9
    return st;
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
  static bool testIterators(const char *name, const Layout &cl, const Layout &pl, const Kernel &k, int threads) {
Ivan Mahonin e865c9
    Stage st(name);
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    assert(cl && pl && k && threads > 0);
Ivan Mahonin e865c9
    Layout::List clist, plist;
Ivan Mahonin e865c9
    cl.split(clist, threads);
Ivan Mahonin e865c9
    pl.split(plist, threads);
Ivan Mahonin e865c9
    
Ivan Mahonin e865c9
    struct I: public Iter {
Ivan Mahonin e865c9
      static inline void init(Neuron &n, Iter::AccumType &a) { ++n.a.i; a.i = (AccumInt)(&n - c_neurons.data()); }
Ivan Mahonin e865c9
      static inline void iter(Neuron &n, Weight &w, Iter::AccumType &a) {
Ivan Mahonin e865c9
        if (w.i)
Ivan Mahonin e865c9
          ++errors;
Ivan Mahonin e865c9
        w.i = (WeightInt)(&n - p_neurons.data() + a.i*p_neurons.size() + 1);
Ivan Mahonin e865c9
      }
Ivan Mahonin e865c9
      static inline void iter2(Neuron &cn, Neuron &pn, Weight &w) {
Ivan Mahonin e865c9
        if (w.i)
Ivan Mahonin e865c9
          ++errors;
Ivan Mahonin e865c9
        w.i = (WeightInt)((&cn - c_neurons.data())*p_neurons.size() + &pn - p_neurons.data() + 1);
Ivan Mahonin e865c9
        pn.v = pn.v + 1;
Ivan Mahonin e865c9
      }
Ivan Mahonin e865c9
    };
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    if (threads == 1) {
Ivan Mahonin e865c9
      Stage st("iterateTestConvolution");
Ivan Mahonin e865c9
      init(cl, pl, k);
Ivan Mahonin e865c9
      iterateTestConvolution(cl, pl, k, c_neurons.data(), p_neurons.data(), weights.data());
Ivan Mahonin e865c9
      verifyNeurons("conv-neurons", cl, c_neurons.data());
Ivan Mahonin e865c9
      verifyWeights("conv-weights", cl, pl, k);
Ivan Mahonin e865c9
    }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    {
Ivan Mahonin e865c9
      Stage st("iterateConvolution");
Ivan Mahonin e865c9
      init(cl, pl, k);
Ivan Mahonin e865c9
      for(int i = 0; i < threads; ++i)
Ivan Mahonin e865c9
        iterateConvolution(clist[i], pl, cl, k, c_neurons.data(), p_neurons.data(), weights.data());
Ivan Mahonin e865c9
      verifyNeurons("conv-neurons", cl, c_neurons.data());
Ivan Mahonin e865c9
      verifyWeights("conv-weights", cl, pl, k);
Ivan Mahonin e865c9
    }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    {
Ivan Mahonin e865c9
      Stage st("iterateConvolutionPoint");
Ivan Mahonin e865c9
      init(cl, pl, k);
Ivan Mahonin e865c9
      int e = errors;
Ivan Mahonin e865c9
      for(int ky = 0; ky < k.sy && errors == e; ++ky)
Ivan Mahonin e865c9
      for(int kx = 0; kx < k.sx && errors == e; ++kx) {
Ivan Mahonin e865c9
        for(int i = 0; i < threads; ++i)
Ivan Mahonin e865c9
          iterateConvolutionPoint(clist[i], pl, cl, k, kx, ky, c_neurons.data(), p_neurons.data(), weights.data());
Ivan Mahonin e865c9
        if (!verifyNeuronsAccum(pl, p_neurons.data(), cl.getD(), true))
Ivan Mahonin e865c9
          printf("kx: %d, ky: %d\n", kx, ky), k.printYX("kernel");
Ivan Mahonin e865c9
      }
Ivan Mahonin e865c9
      verifyNeurons("conv-neurons", pl, p_neurons.data(), true);
Ivan Mahonin e865c9
      verifyWeights("conv-weights", cl, pl, k);
Ivan Mahonin e865c9
    }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    return st;
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
  static bool testIterators(const char *name, const Layout &cl, const Layout &pl, const Kernel &k) {
Ivan Mahonin e865c9
    Stage st(name);
Ivan Mahonin e865c9
    testIterators( "single-thread", cl, pl, k,   1 );
Ivan Mahonin e865c9
    testIterators( "2-threads",     cl, pl, k,   2 );
Ivan Mahonin e865c9
    testIterators( "7-threads",     cl, pl, k,   7 );
Ivan Mahonin e865c9
    testIterators( "8-threads",     cl, pl, k,   8 );
Ivan Mahonin e865c9
    testIterators( "512-threads",   cl, pl, k, 512 );
Ivan Mahonin e865c9
    return st;
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
  
Ivan Mahonin e865c9
  static bool test(const char *name, const Layout &cl, const Layout &pl, const Kernel &k) {
Ivan Mahonin e865c9
    Stage st(name);
Ivan Mahonin e865c9
    
Ivan Mahonin e865c9
    testIterators("iterators", cl, pl, k);
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    {
Ivan Mahonin e865c9
      Layer l(nullptr, pl);
Ivan Mahonin e865c9
      new LayerConv<funcSigmoidExp>(l, cl, k);
Ivan Mahonin b579b3
      testLayer("LayerConv", l);
Ivan Mahonin e865c9
    }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
    {
Ivan Mahonin 8e5348
      Layer l(nullptr, cl);
Ivan Mahonin 8e5348
      new LayerDeconv<funcSigmoidExp>(l, pl, k);
Ivan Mahonin b579b3
      testLayer("LayerDeconv", l);
Ivan Mahonin e865c9
    }
Ivan Mahonin e865c9
Ivan Mahonin 8e5348
    {
Ivan Mahonin 8e5348
      Layer l(nullptr, pl);
Ivan Mahonin 8e5348
      new LayerConvShared<funcSigmoidExp>(l, cl, k);
Ivan Mahonin b579b3
      testLayer("LayerConvShared", l);
Ivan Mahonin 8e5348
    }
Ivan Mahonin 8e5348
Ivan Mahonin 8e5348
    {
Ivan Mahonin 8e5348
      Layer l(nullptr, cl);
Ivan Mahonin 8e5348
      new LayerDeconvShared<funcSigmoidExp>(l, pl, k);
Ivan Mahonin b579b3
      testLayer("LayerDeconvShared", l);
Ivan Mahonin 8e5348
    }
Ivan Mahonin 8e5348
Ivan Mahonin e865c9
    return st;
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
  static bool test(const char *name = "convolution") {
Ivan Mahonin e865c9
    Stage st(name);
Ivan Mahonin e865c9
    test( "square", Layout(64, 64, 4), Layout(128, 128, 4).expandXY(2),                 Kernel(5, 2, -2)           );
Ivan Mahonin e865c9
    test( "rect1",  Layout(63, 43, 5), Layout( 63,  85, 3).expandX(2).   expandY(3),    Kernel(5, 7, 1, 2, -2, -3) );
Ivan Mahonin e865c9
    test( "rect2",  Layout(43, 63, 3), Layout( 85,  63, 5).expandX(3).   expandY(3, 2), Kernel(7, 5, 2, 1, -3, -2) );
Ivan Mahonin e865c9
    test( "rect3",  Layout(64, 48, 5), Layout( 64,  96, 3).expandX(1, 2).expandY(3, 1), Kernel(4, 6, 1, 2, -1, -3) );
Ivan Mahonin e865c9
    test( "pad",    Layout(64, 48, 5).expandX(3, 4).expandY(4, 3).expandZ(5, 4),
Ivan Mahonin e865c9
                    Layout(64, 96, 3).expandX(6, 5).expandY(7, 6).expandZ(0, 1),        Kernel(4, 6, 1, 2, -1, -3) );
Ivan Mahonin e865c9
    return st;
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
};
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
#endif