#include #include #include "common.h" std::atomic_ullong CallCounterV::count{}; std::atomic_ullong CallCounterII::count{}; namespace expar { auto buildTestFunction() { auto callCounterv = alsk::edsl::makeOperand(); auto callCounterii = alsk::edsl::makeOperand(); auto loop = seq(3*callCounterv); auto serial = link()>(callCounterv, loop); auto itersel = (callCounterv, &link)>(5*link(int)>(serial)) ->* callCounterii); auto farmsel = link(7*link()>(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 coresList{1, 2, 3, 7, 11*7-1, 11*7, 11*7+1, maxCores}; } namespace exacc { auto buildTestFunction() { auto callCounterv = alsk::edsl::makeOperand(); auto callCounterii = alsk::edsl::makeOperand(); auto loop = seq(3*callCounterv); auto serial = link()>(callCounterv, loop); auto itersel = (callCounterv, &link)>(5*link(int)>(serial)) ->* callCounterii); auto farm = link()>(7*itersel, callCounterv); auto farmsel = link(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 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 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(); auto esel = alsk::edsl::makeOperand(); auto loop = seq(3*etask); auto serial = link()>(etask, (2*loop)); auto farmsel = link(5*serial) ->* esel; return link()>(farmsel, farmsel); } } using namespace alsk; using Executors = std::tuple< exec::DynamicPool, exec::FirstLevelEqui, exec::FirstLevelGreedy, exec::FirstLevelNoOpti, exec::Sequential, exec::StaticPool, exec::StaticPoolId, exec::StaticThread >; TEMPLATE_LIST_TEST_CASE("Executors", "[executors]", Executors) { CAPTURE(tmp::typeName()); SECTION("executeParallel") { using namespace expar; auto e = buildTestFunction(); for(auto cores: coresList) { auto f = edsl::implement::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::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()); auto e = buildTestFunction(); for(std::size_t upTo: {2, 3, 4, 5, 6, 7, 8}) { CAPTURE(upTo); auto f = edsl::implement::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(); } } }