/**
* Parallel Code Count
* test.cpp
* Code counting speed testing code.
*/
#include <iostream>
#include <algorithm>
#include <chrono>
#include <type_traits>
#include "random_string.h"
#include "reference.h"
#include "atomic.h"
#include "parallel.h"
#include "std_atomic.h"
using namespace std;
const size_t STRING_SIZE_MAX = 1u << 27, // maximal size of a random string
STRING_SIZE_MIN = 1u << 22, // minimal size of a random string
ROUNDS = 10; // repeat each test ROUNDS times
// returns success (compares result of CountTestFunctor to reference single-threaded implementation)
template <class CountTestFunctor>
bool do_test(volatile double &seconds_sum, const string &s)
{
int amount[COUNTERS] = {};
CountTestFunctor F;
// start timer
const auto t0 = chrono::high_resolution_clock::now();
#pragma omp flush (t0)
F(s, amount);
#pragma omp flush (amount)
const auto t1 = chrono::high_resolution_clock::now();
// stopped timer
seconds_sum += chrono::duration<double>(t1 - t0).count();
// check if non-reference
if (!is_same<CountTestFunctor, ReferenceCountCodes>::value)
{
int ref_amount[COUNTERS] = {};
ReferenceCountCodes()(s, ref_amount);
return equal(amount, amount + COUNTERS, ref_amount);
}
return true;
}
// reports the resulting time (and failures if any) via cout
template <class CountTestFunctor, class SeedGen>
void do_rounds(SeedGen sg, size_t string_size)
{
volatile double sum; // volatile to prevent some possible compiler optimizations
// warming up
do_test<CountTestFunctor>(sum, RandomString<>(sg())(string_size));
sum = 0.0;
for (auto r = ROUNDS; r != 0; --r)
{
if (!do_test<CountTestFunctor>(sum, RandomString<>(sg())(string_size)))
cout << "failed ";
}
cout << sum / ROUNDS;
}
int main()
{
cout << "ParallelCodeCount, OpenMP max threads: " << omp_get_max_threads();
cout << "\n rounds: " << ROUNDS;
cout << "\n time in seconds\n";
mt19937 rng;
uniform_int_distribution<unsigned> seeds;
for (size_t sz = STRING_SIZE_MAX; sz >= STRING_SIZE_MIN; sz /= 2u)
{
cout << "\n string size: " << double(sz) / (1 << 20) << "Mb\n";
auto sg = [&rng, &seeds]() { return seeds(rng); };
cout << "reference: ";
do_rounds<ReferenceCountCodes>(sg, sz);
cout << "\natomic: ";
do_rounds<AtomicCountCodes>(sg, sz);
cout << "\nstd::atomic: ";
do_rounds<StdAtomicCountCodes>(sg, sz);
cout << "\nparallel: ";
do_rounds<ParallelCountCodes>(sg, sz);
cout << endl;
}
}