Commit a529012b authored by Florian Schmaus's avatar Florian Schmaus
Browse files

Merge branch 'pulse-mode' into 'master'

add additional mode of introducing work

See merge request i4/manycore/emper!383
parents 534207e9 5720c0d8
......@@ -149,7 +149,7 @@ class AbstractSemaphoreWorkerSleepStrategy
* The overhead of increasing the semaphore "to" much are unnessesary atomic
* operations on global state. This overhead was not measured in contrast to
* the harm caused to latency by beeing greedy when using the semaphore.
* the harm caused to latency by beeing parsimonious when using the semaphore.
* Note that sem_getvalue() is allowed to return 0 if there are
* waiting workers, hence we need to set the threshold atleast to
......
......@@ -9,6 +9,7 @@
#include <exception>
#include <fstream> // IWYU pragma: keep
#include <iostream>
#include <sstream>
#include <string>
#include "CountingPrivateSemaphore.hpp"
......@@ -22,6 +23,39 @@ namespace po = boost::program_options;
using Clock = std::chrono::high_resolution_clock;
using TimePoint = std::chrono::time_point<Clock>;
enum class PulseMode {
Burst, /*!< Introduce all work as fast as possible */
Even, /*!< Introduce work evenly during the pulse */
};
auto operator<<(std::ostream& out, const PulseMode& mode) -> std::ostream& {
switch (mode) {
case PulseMode::Burst:
out << "burst";
break;
case PulseMode::Even:
out << "even";
break;
}
return out;
}
auto operator>>(std::istream& in, PulseMode& mode) -> std::istream& {
std::string token;
in >> token;
if (token == "burst") {
mode = PulseMode::Burst;
} else if (token == "even") {
mode = PulseMode::Even;
} else {
in.setstate(std::ios_base::failbit);
}
return in;
}
static PulseMode pulseMode;
// Pulse of new work in microseconds
static int64_t pulse = 1L * 1000 * 1000;
// Number of pulses
......@@ -62,18 +96,25 @@ static void pulser(Runtime& runtime) {
const workerid_t workerCount = runtime.getWorkerCount();
const workerid_t workItems = (workerCount * utilization) / 100;
struct timespec ts {
0, 0
};
// TODO: better calculate the time until the next burst
if (pulseMode == PulseMode::Burst)
ts.tv_nsec = pulse * 1000;
else
ts.tv_nsec = (pulse * 1000) / workItems;
CPS cps;
for (unsigned i = 0; i < iterations; ++i) {
for (unsigned w = 0; w < workItems; ++w) {
Work* work = new Work();
spawn([=] { work->run(); }, cps);
if (pulseMode == PulseMode::Even) emper::nanosleep(&ts);
}
// TODO: better calculate the time until the next pulse
struct timespec ts {
.tv_sec = 0, .tv_nsec = pulse * 1000
};
emper::nanosleep(&ts);
// TODO: Think about busy looping for small times
if (pulseMode == PulseMode::Burst) emper::nanosleep(&ts);
}
cps.wait();
runtime.initiateTermination();
......@@ -134,6 +175,7 @@ auto main(int argc, char* argv[]) -> int {
("utilization", po::value<unsigned>(&utilization)->default_value(utilization),
"The target utilization of the runtime")
("latencies-file", po::value<std::string>(), "File to store all collected latencies")
("pulse-mode", po::value<PulseMode>(&pulseMode)->default_value(PulseMode::Burst), "How to introducing the work")
;
// clang-format on
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment