#ifndef SEGMENT_TEST_INC_CPP
#define SEGMENT_TEST_INC_CPP
#include "test.inc.cpp"
#include "segment.inc.cpp"
class SegmentTest: public Test {
public:
static bool testSegment(const char *name, Segment &segment, Layout l, int x, int y, int z, NeuronReal trainRatio) {
Stage st(name);
struct H {
Segment &segment;
int x, y, z;
Quality testQ;
NeuronReal ratio;
std::vector<std::thread*> threads;
std::vector<Quality> qualities;
std::atomic<unsigned int> counter;
H(Segment &segment, int x, int y, int z, NeuronReal ratio): segment(segment), x(x), y(y), z(z), ratio(ratio), counter(0) { }
void prepareData()
{ memcpy(segment.weights, weights.data(), segment.weightsCount*sizeof(Weight)); }
void func(int tid, unsigned int seed) {
Barrier barrier(counter, tid, threads.size(), seed);
qualities[tid] = segment.pass(barrier, x, y, z, ratio);
}
bool test(const char *name, int threadsCount) {
Stage st(name);
assert(threadsCount > 0);
counter = 0;
threads.clear();
qualities.clear();
threads.resize(threadsCount, nullptr);
qualities.resize(threadsCount);
prepareData();
segment.split(threadsCount);
for(int i = 1; i < threadsCount; ++i) threads[i] = new std::thread(&H::func, this, i, rand());
func(0, rand());
Quality q = qualities[0];
for(int i = 1; i < threadsCount; ++i) { threads[i]->join(); delete threads[i]; q += qualities[i]; }
threads.clear();
if ( fabs(q.train - testQ.train) > 1e-10
|| fabs(q.human - testQ.human) > 1e-10 )
{
printf("qualities differs, was %g (%g), expected %g (%g)\n",
q.human, q.train, testQ.human, testQ.train );
++errors;
}
for(int i = 0; i < segment.weightsCount; ++i) {
WeightReal a = segment.weights[i].w;
WeightReal b = weights[i + segment.weightsCount].w;
if (fabs(a - b) > 1e-10) {
printf("weights differs at %d, was %g, expected %g\n", i, a, b);
segment.layout.printYXZ("layout");
++errors; break;
}
}
return st;
}
} h(segment, x, y, z, trainRatio);
assert(segment.weightsCount > 0);
int valuesCount = l.getCount();
init(0, 0, segment.weightsCount*3, valuesCount);
for(int i = 0; i < valuesCount; ++i)
values[i] = rand()/(NeuronReal)RAND_MAX;
for(int i = 0; i < segment.weightsCount; ++i)
weights[i].w = (WeightReal)(2.0*rand()/RAND_MAX - 1);
segment.layout = l;
segment.f_values = values.data();
segment.weights = &weights[segment.weightsCount];
segment.check(x, y, z);
h.prepareData();
h.testQ = segment.testPass(x, y, z, trainRatio);
segment.weights += segment.weightsCount;
h.test("single-thread", 1);
h.test("single-thread-repeat", 1);
h.test("2-threads", 2);
h.test("7-threads", 7);
h.test("7-threads-repeat", 7);
h.test("8-threads", 8);
return st;
}
};
#endif