107 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			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);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |