alsk/tests/executor/common.cpp

162 lines
4.0 KiB
C++
Raw Permalink Normal View History

2021-05-10 16:14:13 +00:00
#include <catch.hpp>
#include <tmp/debug.h>
#include "common.h"
std::atomic_ullong CallCounterV::count{};
std::atomic_ullong CallCounterII::count{};
namespace expar {
auto buildTestFunction() {
auto callCounterv = alsk::edsl::makeOperand<int(), CallCounterV>();
auto callCounterii = alsk::edsl::makeOperand<int(int, int), CallCounterII>();
auto loop = seq(3*callCounterv);
auto serial = link<R<0>()>(callCounterv, loop);
auto itersel = (callCounterv, &link<int(R<0>)>(5*link<R<0>(int)>(serial)) ->* callCounterii);
auto farmsel = link<int()>(7*link<R<1>()>(itersel, callCounterv)) ->* callCounterii;
auto farm = 11*farmsel;
return farm;
}
constexpr auto countV() { return 11 * 7 * (1 + 5 * (1 + 3) + 1); }
constexpr auto countII() { return 11 * ((7 - 1) + 7 * 5); }
constexpr auto maxCores = 11*7 * 64;
constexpr std::array<decltype(maxCores), 8> coresList{1, 2, 3, 7, 11*7-1, 11*7, 11*7+1, maxCores};
}
namespace exacc {
auto buildTestFunction() {
auto callCounterv = alsk::edsl::makeOperand<int(), CallCounterV>();
auto callCounterii = alsk::edsl::makeOperand<int(int, int), CallCounterII>();
auto loop = seq(3*callCounterv);
auto serial = link<R<0>()>(callCounterv, loop);
auto itersel = (callCounterv, &link<int(R<0>)>(5*link<R<0>(int)>(serial)) ->* callCounterii);
auto farm = link<R<1>()>(7*itersel, callCounterv);
auto farmsel = link<int()>(11*farm) ->* callCounterii;
return farmsel;
}
constexpr auto countV() { return 11 * (7 * (1 + 5 * (1 + 3)) + 1); }
constexpr auto countII() { return (11-1) + 11 * 7 * 5; }
constexpr auto maxCores = 11*7 * 64;
constexpr std::array<decltype(maxCores), 8> coresList{1, 2, 3, 7, 11*7-1, 11*7, 11*7+1, maxCores};
}
namespace repeatability {
using PRNG = std::mt19937;
int task(PRNG& rng, std::size_t) {
std::uniform_int_distribution<int> dist(-100, 100);
int a = dist(rng);
std::this_thread::sleep_for(std::chrono::milliseconds(0));
int b = dist(rng);
return a - b;
}
int sel(int a, int b) { return a + b; }
auto buildTestFunction() {
auto etask = alsk::edsl::makeOperand<int(RNG, CtxId), FN(task)>();
auto esel = alsk::edsl::makeOperand<int(int, int), FN(sel)>();
auto loop = seq(3*etask);
auto serial = link<R<0>()>(etask, (2*loop));
auto farmsel = link<int()>(5*serial) ->* esel;
return link<R<1>()>(farmsel, farmsel);
}
}
using namespace alsk;
using Executors = std::tuple<
exec::DynamicPool<void>,
exec::FirstLevelEqui<void>,
exec::FirstLevelGreedy<void>,
exec::FirstLevelNoOpti<void>,
exec::Sequential<void>,
exec::StaticPool<void>,
exec::StaticPoolId<void>,
exec::StaticThread<void>
>;
TEMPLATE_LIST_TEST_CASE("Executors", "[executors]", Executors) {
CAPTURE(tmp::typeName<TestType>());
SECTION("executeParallel") {
using namespace expar;
auto e = buildTestFunction();
for(auto cores: coresList) {
auto f = edsl::implement<GetExecutor<TestType>::template Template>(e);
f.executor.cores = cores;
CallCounterV::count = 0;
CallCounterII::count = 0;
f();
REQUIRE(CallCounterV::count == countV());
REQUIRE(CallCounterII::count == countII());
}
}
SECTION("executeParallelAccumulate") {
using namespace exacc;
auto e = buildTestFunction();
for(auto cores: coresList) {
auto f = edsl::implement<GetExecutor<TestType>::template Template>(e);
f.executor.cores = cores;
CallCounterV::count = 0;
CallCounterII::count = 0;
f();
REQUIRE(CallCounterV::count == countV());
REQUIRE(CallCounterII::count == countII());
}
}
}
TEMPLATE_LIST_TEST_CASE("Repeatability", "[executors][repeatability]", Executors) {
using namespace repeatability;
CAPTURE(tmp::typeName<TestType>());
auto e = buildTestFunction();
for(std::size_t upTo: {2, 3, 4, 5, 6, 7, 8}) {
CAPTURE(upTo);
auto f = edsl::implement<GetExecutor<TestType>::template Template>(e);
f.executor.repeatability.upTo(upTo);
f.executor.cores = 1;
auto expected = f();
f.state.context.reset();
for(std::size_t cores = 2; cores <= upTo; ++cores) {
CAPTURE(cores);
f.executor.cores = cores;
REQUIRE(f() == expected);
f.state.context.reset();
}
}
}