#include #include #include #include "pls/pls.h" constexpr int MAX_NUM_TASKS = 32; constexpr int MAX_STACK_SIZE = 1024 * 8; TEST_CASE("spawn/sync invoke calls correctly", "[algorithms/invoke.h]") { pls::scheduler scheduler{3, MAX_NUM_TASKS, MAX_STACK_SIZE}; std::atomic num_run{0}; scheduler.perform_work([&] { pls::spawn([&] { num_run++; while (num_run < 3); }); pls::spawn([&] { while (num_run < 1); num_run++; while (num_run < 3); }); pls::spawn([&] { while (num_run < 2); num_run++; }); pls::sync(); REQUIRE(num_run == 3); }); } TEST_CASE("parallel invoke calls correctly", "[algorithms/invoke.h]") { pls::scheduler scheduler{3, MAX_NUM_TASKS, MAX_STACK_SIZE}; std::atomic num_run{0}; scheduler.perform_work([&] { pls::invoke([&] { num_run++; while (num_run < 3); }, [&] { while (num_run < 1); num_run++; while (num_run < 3); }, [&] { while (num_run < 2); num_run++; }); REQUIRE(num_run == 3); }); } TEST_CASE("parallel for calls correctly (might fail, timing based)", "[algorithms/for_each.h]") { pls::scheduler scheduler{8, MAX_NUM_TASKS, MAX_STACK_SIZE}; auto start = std::chrono::steady_clock::now(); std::atomic work_done{0}; scheduler.perform_work([&] { pls::for_each_range(0, 100, [&](const int) { work_done++; std::this_thread::sleep_for(std::chrono::milliseconds(1)); }); }); auto end = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast(end - start).count(); REQUIRE(work_done == 100); // It makes sense that 100 iterations on at least 4 threads take less than half the serial time. // We want to make sure that at least some work is distributed on multiple cores. REQUIRE(elapsed <= 50); } TEST_CASE("reduce calls correctly (might fail, timing based)", "[algorithms/for_each.h]") { pls::scheduler scheduler{8, MAX_NUM_TASKS, MAX_STACK_SIZE}; auto start = std::chrono::steady_clock::now(); int num_elements = 100; pls::range range{1, num_elements + 1}; int result; scheduler.perform_work([&] { result = pls::reduce(range.begin(), range.end(), 0, [&](const int a, const int b) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); return a + b; }); }); auto end = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast(end - start).count(); REQUIRE(result == (num_elements * (num_elements + 1)) / 2); // It makes sense that 100 iterations on at least 4 threads take less than half the serial time. // We want to make sure that at least some work is distributed on multiple cores. REQUIRE(elapsed <= 50); }