alsk/tests/farmsel.cpp

107 lines
2.4 KiB
C++

#include <catch.hpp>
#include <atomic>
#include <alsk/alsk.h>
#include <random>
#include "common.h"
using namespace alsk;
TEST_CASE("FarmSel") {
constexpr std::size_t n = 1024;
SECTION("basic test") {
using Data = int;
using Task = std::function<Data()>;
using Accu = std::function<Data(Data const&, Data const&)>;
std::atomic_size_t countTask, countAccu;
Task task = [&]{
++countTask;
return 42;
};
Accu accu = [&](Data const& a, Data const& b) {
++countAccu;
return std::min(a, b);
};
using Skel = decltype(getSkeleton((*edsl::makeOperand<Data(), Task>()) ->* edsl::makeOperand<Data(Data, Data), Accu>()));
auto f = implement<exec::FirstLevelEqui, Skel>();
f.skeleton.n = n;
f.skeleton.task = task;
f.skeleton.select = accu;
countTask = countAccu = 0;
SECTION("cores = 1") {
f.executor.cores = 1;
Data d = f();
REQUIRE(d == 42);
REQUIRE(countTask == f.skeleton.n);
REQUIRE(countAccu == f.skeleton.n-1);
}
SECTION("cores = 2") {
f.executor.cores = 2;
Data d = f();
REQUIRE(d == 42);
REQUIRE(countTask == f.skeleton.n);
REQUIRE(countAccu == f.skeleton.n-1);
}
}
SECTION("repeatability") {
using Data = std::tuple<int, std::string>;
using RNG = std::mt19937;
using Task = std::function<Data(RNG&)>;
using Accu = std::function<Data(Data const&, Data const&)>;
std::atomic_size_t countTask, countAccu;
Task task = [&](RNG& rng) {
std::uniform_int_distribution<int> dist{0, 32};
std::uniform_int_distribution<int> text{0, n*n};
++countTask;
return Data{dist(rng), std::to_string(text(rng))};
};
Accu accu = [&](Data const& a, Data const& b) {
++countAccu;
return std::get<0>(a) < std::get<0>(b)? a:b;
};
using Struct = S<FarmSel, Task, Accu>;
using Links = L<FarmSel, Data(), Data(arg::RNG), Data(Data, Data)>;
using Skel = BuildSkeletonT<Struct, Links>;
auto f = implement<exec::FirstLevelEqui, Skel>();
f.skeleton.n = n;
f.skeleton.task = task;
f.skeleton.select = accu;
f.executor.cores = 1;
Data expected = f();
countTask = countAccu = 0;
for(std::size_t k = 1; k <= 2; k *= 2) {
SECTION("cores = "+std::to_string(k)) {
f.executor.cores = k;
f.state.context.reset();
Data d = f();
REQUIRE(std::get<0>(d) == std::get<0>(expected));
REQUIRE(std::get<1>(d) == std::get<1>(expected));
REQUIRE(countTask == f.skeleton.n);
REQUIRE(countAccu == f.skeleton.n-1);
}
}
}
}