162 lines
4.0 KiB
C++
162 lines
4.0 KiB
C++
|
#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();
|
||
|
}
|
||
|
}
|
||
|
}
|