summaryrefslogtreecommitdiff
path: root/Simulator/include/simulation
diff options
context:
space:
mode:
authorMDBijman <matthijs@bijman.org>2017-01-24 12:15:26 +0100
committerMDBijman <matthijs@bijman.org>2017-01-24 12:15:26 +0100
commit070ce923574dcc57435cb3fb2dfe86b6a38cd249 (patch)
treeffd69a842ac4ad22aaf7161f923b9f0b47c7147a /Simulator/include/simulation
Initial code commit with organized dependencies
Diffstat (limited to 'Simulator/include/simulation')
-rw-r--r--Simulator/include/simulation/Experiment.h179
-rw-r--r--Simulator/include/simulation/Path.h63
-rw-r--r--Simulator/include/simulation/Section.h76
-rw-r--r--Simulator/include/simulation/history/History.h43
-rw-r--r--Simulator/include/simulation/history/MachineSnapshot.h17
-rw-r--r--Simulator/include/simulation/history/SimulationHistory.h81
-rw-r--r--Simulator/include/simulation/history/WorkloadSnapshot.h13
-rw-r--r--Simulator/include/simulation/schedulers/FirstInFirstOutScheduler.h37
-rw-r--r--Simulator/include/simulation/schedulers/Scheduler.h25
-rw-r--r--Simulator/include/simulation/schedulers/ShortestRemainingTimeScheduler.h46
-rw-r--r--Simulator/include/simulation/workloads/Workload.h80
-rw-r--r--Simulator/include/simulation/workloads/WorkloadPool.h43
12 files changed, 703 insertions, 0 deletions
diff --git a/Simulator/include/simulation/Experiment.h b/Simulator/include/simulation/Experiment.h
new file mode 100644
index 00000000..69c192fa
--- /dev/null
+++ b/Simulator/include/simulation/Experiment.h
@@ -0,0 +1,179 @@
+#pragma once
+#include "Path.h"
+#include <algorithm>
+#include "workloads/WorkloadPool.h"
+
+namespace Simulation
+{
+ /**
+ * \brief Holds a Path, Scheduler, and WorkloadPool together to form a single unit that can be simulated.
+ */
+ class Experiment
+ {
+ public:
+ /**
+ * \brief Instantiates a new, complete, experiment that starts at tick 0 and can be simulated.
+ * \param path The path this experiment should simulate.
+ * \param scheduler The scheduler this experiment should use for workload balancing.
+ * \param pool The workloadPool that contains the workloads of this experiment.
+ * \param id The id of this experiment as it is in the database.
+ */
+ Experiment(Path path, Scheduler* scheduler, WorkloadPool pool, uint32_t id) : path(path), scheduler(scheduler), id(id), currentTick(0), workloadPool(pool)
+ {}
+
+ /**
+ * \brief Simulates a single tick of this experiment.
+ */
+ void tick()
+ {
+ if(finished) return;
+
+ workloadPool.clearFinishedWorkloads();
+
+ auto machineAccumulator = path.getCurrentSection(currentTick).getMachines();
+
+ // Schedule the workload over each machine
+ scheduler->schedule(machineAccumulator, workloadPool.getWorkloads(currentTick));
+
+ // Update each machine
+ std::for_each(
+ machineAccumulator.begin(),
+ machineAccumulator.end(),
+ [this](const std::reference_wrapper<Modeling::Machine>& machineWrapper) {
+ machineWrapper.get().work();
+ }
+ );
+
+ currentTick++;
+
+ if(workloadPool.isEmpty()) finished = true;
+ }
+
+ /**
+ * \brief Saves the state of the simulation, adding it to the history.
+ */
+ void saveState()
+ {
+ for(Workload* workload : workloadPool.getWorkloads(currentTick))
+ {
+ history.addSnapshot(
+ currentTick,
+ WorkloadSnapshot(
+ workload->getId(),
+ workload->getRemainingOperations()
+ )
+ );
+ }
+
+ for(std::reference_wrapper<Modeling::Machine> machineref : path.getCurrentSection(currentTick).getMachines())
+ {
+ auto machine = machineref.get();
+ history.addSnapshot(
+ currentTick,
+ MachineSnapshot(
+ machine.getId(),
+ machine.getWorkloadId(),
+ machine.getTemperature(),
+ machine.getLoad(),
+ machine.getMemory()
+ )
+ );
+ }
+ }
+
+ /**
+ * \brief Adds the given workload to the pool of workloads of this simulation.
+ * \param wl The workload to add to the simulator of this experiment.
+ */
+ void addWorkload(Workload& wl)
+ {
+ workloadPool.addWorkload(wl);
+ }
+
+ /**
+ * \return A reference to the workloads of this simulation.
+ */
+ WorkloadPool& getWorkloadPool()
+ {
+ return workloadPool;
+ }
+
+ /**
+ * \return The current tick which is being simulated, i.e. the number of ticks that have passed.
+ */
+ uint32_t getCurrentTick() const
+ {
+ return currentTick;
+ }
+
+ /**
+ * \return The history of this experiment that has no yet been written to the database.
+ */
+ SimulationHistory getHistory() const
+ {
+ return history;
+ }
+
+ /**
+ * \return The id of this experiment as it is in the database.
+ */
+ uint32_t getId() const
+ {
+ return id;
+ }
+
+ /**
+ * \brief Sets this experiment to finished. After calling this method,
+ * the tick() method will have no effect.
+ */
+ void end()
+ {
+ this->finished = true;
+ }
+
+ /**
+ * \return True if the experiment is finished, i.e. when all workloads have been completed.
+ */
+ bool isFinished() const
+ {
+ return this->finished;
+ }
+
+ private:
+ /**
+ * \brief The path of this experiment which contains the sections and when they should be used.
+ */
+ Path path;
+
+ /**
+ * \brief The scheduler that this used for workload balancing.
+ */
+ std::shared_ptr<Scheduler> scheduler;
+
+ /**
+ * \brief The id of this experiment as it is in the database.
+ */
+ uint32_t id;
+
+ /**
+ * \brief The number of ticks that have passed.
+ */
+ uint32_t currentTick;
+
+ /**
+ * \brief The pool of workloads in this simulation, to be distributed by the scheduler.
+ */
+ WorkloadPool workloadPool;
+
+ /**
+ * \brief The part of the history of this simulation which has not been written to the database.
+ */
+ SimulationHistory history;
+
+ /**
+ * \brief If this is true, then tick will not do anything. This indicates that the simulation is finished,
+ * and that its history should be written to disk.
+ */
+ bool finished = false;
+ };
+}
diff --git a/Simulator/include/simulation/Path.h b/Simulator/include/simulation/Path.h
new file mode 100644
index 00000000..d35d49fc
--- /dev/null
+++ b/Simulator/include/simulation/Path.h
@@ -0,0 +1,63 @@
+#pragma once
+#include "Section.h"
+#include "modeling/ModelingTypes.h"
+
+namespace Simulation
+{
+ /**
+ * \brief Holds all sections of the parent experiment, and returns the correct one
+ * based on the current tick.
+ */
+ class Path
+ {
+ public:
+ explicit Path(int id) : id(id)
+ {}
+
+
+ /**
+ * \brief Adds the given section to this path. The begin tick of this section
+ * should not already be in use by one of the other sections in this path.
+ * \param section The section to add to this path.
+ */
+ void addSection(DefaultSection section)
+ {
+ sections.push_back(section);
+ }
+
+ /**
+ * \brief Returns the section that is currently in use by taking the section
+ * that has the greatest begin tick smaller than the current tick
+ * \param currentTick The tick the simulator is simulating right now.
+ * \return The section that is currently in use.
+ */
+ DefaultSection& getCurrentSection(uint32_t currentTick)
+ {
+ size_t currentSection = 0;
+
+ uint32_t currentStartTick = 0;
+ for(int i = 0; i < sections.size(); ++i)
+ {
+ uint32_t tempStartTick = sections.at(i).getStartTick();
+ if(tempStartTick > currentStartTick && tempStartTick < currentTick)
+ currentSection = i;
+ }
+
+ return sections.at(currentSection);
+ }
+
+ private:
+
+ /**
+ * \brief The unordered vector of sections in this path. No pair of sections
+ * should share the same begin tick.
+ */
+ std::vector<DefaultSection> sections;
+
+
+ /**
+ * \brief The id of this path as it is in the database.
+ */
+ int id;
+ };
+}
diff --git a/Simulator/include/simulation/Section.h b/Simulator/include/simulation/Section.h
new file mode 100644
index 00000000..3c11b073
--- /dev/null
+++ b/Simulator/include/simulation/Section.h
@@ -0,0 +1,76 @@
+#pragma once
+#include "modeling/Datacenter.h"
+#include "modeling/Room.h"
+#include "simulation/history/SimulationHistory.h"
+
+#include <vector>
+#include <iterator>
+
+namespace Simulation
+{
+ /**
+ * \brief Holds a datacenter and the tick on which the parent experiment should switch to this section.
+ * \tparam DatacenterType The type of datacenter to be used.
+ */
+ template<typename DatacenterType>
+ class Section
+ {
+ public:
+ /**
+ * \brief Initializes the datacenter in the simulation. Sets paused to false and finished to false.
+ * \param dc The topology of this section.
+ * \param startTick The tick on which the experiment should start using the topology of this section.
+ */
+ Section(DatacenterType& dc, uint32_t startTick) : datacenter(dc), startTick(startTick)
+ {}
+
+ /**
+ * \return A reference to the datacenter of this section.
+ */
+ DatacenterType& getDatacenter()
+ {
+ return datacenter;
+ }
+
+ /**
+ * \return All machines in the datacenter of section.
+ */
+ std::vector<std::reference_wrapper<Modeling::Machine>> getMachines()
+ {
+ using namespace std;
+
+ vector<reference_wrapper<Modeling::Machine>> machineAccumulator;
+
+ // For each serverroom, we get the racks in the room
+ vector<Modeling::ServerRoom>& rooms = datacenter.template getRoomsOfType<Modeling::ServerRoom>();
+ for(auto& room : rooms)
+ // For each rack get the machines inside that rack
+ for(auto& rack : room.getEntitiesOfType<Modeling::Rack>())
+ // Add each machine to the accumulator
+ for(auto& machine : rack.getMachines())
+ machineAccumulator.push_back(ref(machine.second));
+
+ return machineAccumulator;
+ }
+
+ /**
+ * \return The tick on which the experiment should start using the topology of this section.
+ */
+ uint32_t getStartTick() const
+ {
+ return startTick;
+ }
+
+ private:
+ /**
+ * \brief The datacenter that is used for experiments.
+ */
+ DatacenterType datacenter;
+
+ /**
+ * \brief The tick when the next sections starts. This is -1 if this is the last section.
+ */
+ uint32_t startTick;
+ };
+
+}
diff --git a/Simulator/include/simulation/history/History.h b/Simulator/include/simulation/history/History.h
new file mode 100644
index 00000000..f1d826eb
--- /dev/null
+++ b/Simulator/include/simulation/history/History.h
@@ -0,0 +1,43 @@
+#pragma once
+#include <stdint.h>
+#include <map>
+
+namespace Simulation {
+ template<typename Type>
+ class History {
+ public:
+ void addSnapshotAtTick(uint32_t tick, Type snapshot)
+ {
+ history.insert(std::make_pair(tick, snapshot));
+ }
+
+ const auto& snapshotsAtTick(uint32_t tick)
+ {
+ return history.equal_range(tick);
+ }
+
+ typename std::unordered_map<uint32_t, Type>::const_iterator begin()
+ {
+ return history.begin();
+ }
+
+ typename std::unordered_map<uint32_t, Type>::const_iterator end()
+ {
+ return history.end();
+ }
+
+ void clear()
+ {
+ history.clear();
+ }
+
+ size_t size()
+ {
+ return history.size();
+ }
+
+ private:
+ // Maps ticks to histories of workloads
+ std::unordered_multimap<uint32_t, Type> history;
+ };
+} \ No newline at end of file
diff --git a/Simulator/include/simulation/history/MachineSnapshot.h b/Simulator/include/simulation/history/MachineSnapshot.h
new file mode 100644
index 00000000..49ce1313
--- /dev/null
+++ b/Simulator/include/simulation/history/MachineSnapshot.h
@@ -0,0 +1,17 @@
+#pragma once
+
+namespace Simulation {
+ /*
+ POD class that represents the state of a machine.
+ */
+ class MachineSnapshot {
+ public:
+ MachineSnapshot(int id, int currentWorkload, float temp, float load, uint32_t mem) : id(id), currentWorkload(currentWorkload), temperature(temp), loadFraction(load), usedMemory(mem) {}
+
+ int id;
+ int currentWorkload;
+ float temperature;
+ float loadFraction;
+ uint32_t usedMemory;
+ };
+} \ No newline at end of file
diff --git a/Simulator/include/simulation/history/SimulationHistory.h b/Simulator/include/simulation/history/SimulationHistory.h
new file mode 100644
index 00000000..f43968b7
--- /dev/null
+++ b/Simulator/include/simulation/history/SimulationHistory.h
@@ -0,0 +1,81 @@
+#pragma once
+#include "History.h"
+#include "WorkloadSnapshot.h"
+#include "MachineSnapshot.h"
+
+#include <unordered_map>
+
+namespace Simulation
+{
+ using WorkloadHistory = History<WorkloadSnapshot>;
+ using MachineHistory = History<MachineSnapshot>;
+ using HistoryRef = std::tuple<std::reference_wrapper<WorkloadHistory>, std::reference_wrapper<MachineHistory>>;
+
+ class SimulationHistory
+ {
+ public:
+ /*
+ Adds the workload snapshot at the given tick.
+ */
+ void addSnapshot(uint32_t tick, WorkloadSnapshot snapshots)
+ {
+ workloadHistory.addSnapshotAtTick(tick, snapshots);
+ }
+
+ /*
+ Adds the machine snapshot at the given tick.
+ */
+ void addSnapshot(uint32_t tick, MachineSnapshot snapshots)
+ {
+ machineHistory.addSnapshotAtTick(tick, snapshots);
+ }
+
+ /*
+ Returns the equal_range of the workload snapshots at the given tick.
+ */
+ auto getWorkloadSnapshot(uint32_t tick)
+ {
+ return workloadHistory.snapshotsAtTick(tick);
+ }
+
+ /*
+ Returns the equal_range of the machine snapshots at the given tick.
+ */
+ auto getMachineSnapshot(uint32_t tick)
+ {
+ return machineHistory.snapshotsAtTick(tick);
+ }
+
+ /*
+ Returns a const tuple ref of the entire cached history of machines and workloads.
+ */
+ const HistoryRef getHistory()
+ {
+ return std::make_tuple(
+ std::ref(workloadHistory),
+ std::ref(machineHistory)
+ );
+ }
+
+ /*
+ Clears the cache of history.
+ */
+ void clearHistory()
+ {
+ workloadHistory.clear();
+ machineHistory.clear();
+ }
+
+ /*
+ Returns the number of snapshots that are in the history cache.
+ */
+ size_t historySize()
+ {
+ return workloadHistory.size();
+ }
+
+ private:
+ WorkloadHistory workloadHistory;
+ MachineHistory machineHistory;
+ };
+} \ No newline at end of file
diff --git a/Simulator/include/simulation/history/WorkloadSnapshot.h b/Simulator/include/simulation/history/WorkloadSnapshot.h
new file mode 100644
index 00000000..1e7e2695
--- /dev/null
+++ b/Simulator/include/simulation/history/WorkloadSnapshot.h
@@ -0,0 +1,13 @@
+#pragma once
+
+namespace Simulation
+{
+ class WorkloadSnapshot
+ {
+ public:
+ WorkloadSnapshot(uint32_t id, uint32_t flopsDone) : flopsDone(flopsDone), id(id) {}
+
+ uint32_t flopsDone;
+ uint32_t id;
+ };
+} \ No newline at end of file
diff --git a/Simulator/include/simulation/schedulers/FirstInFirstOutScheduler.h b/Simulator/include/simulation/schedulers/FirstInFirstOutScheduler.h
new file mode 100644
index 00000000..0cac0dfa
--- /dev/null
+++ b/Simulator/include/simulation/schedulers/FirstInFirstOutScheduler.h
@@ -0,0 +1,37 @@
+#pragma once
+#include "Scheduler.h"
+#include <algorithm>
+
+namespace Simulation
+{
+ class FirstInFirstOutScheduler : public Scheduler
+ {
+ protected:
+ ~FirstInFirstOutScheduler()
+ {
+ }
+
+ public:
+ /*
+ Distribute workloads according to the FIFO principle
+ */
+ void schedule(std::vector<std::reference_wrapper<Modeling::Machine>>& machines, std::vector<Workload*> workloads) override
+ {
+ if (workloads.size() == 0)
+ return;
+
+ // Find the first workload with dependencies finished
+ int index = 0;
+ while(!workloads.at(index)->dependencyFinished)
+ index = (++index) % workloads.size();
+
+ std::for_each(
+ machines.begin(),
+ machines.end(),
+ [index, &workloads](std::reference_wrapper<Modeling::Machine>& machine) {
+ machine.get().giveTask(workloads.at(index));
+ }
+ );
+ }
+ };
+}
diff --git a/Simulator/include/simulation/schedulers/Scheduler.h b/Simulator/include/simulation/schedulers/Scheduler.h
new file mode 100644
index 00000000..b084e8f6
--- /dev/null
+++ b/Simulator/include/simulation/schedulers/Scheduler.h
@@ -0,0 +1,25 @@
+#pragma once
+#include "simulation/workloads/Workload.h"
+#include "modeling/machine/Machine.h"
+
+#include <vector>
+
+namespace Simulation
+{
+ /*
+ Provides a strategy for load balancing.
+ */
+ class Scheduler
+ {
+ public:
+ virtual ~Scheduler()
+ {
+
+ }
+
+ /*
+ Divides the workloads over the given machines.
+ */
+ virtual void schedule(std::vector<std::reference_wrapper<Modeling::Machine>>& machines, std::vector<Workload*> workloads) = 0;
+ };
+}
diff --git a/Simulator/include/simulation/schedulers/ShortestRemainingTimeScheduler.h b/Simulator/include/simulation/schedulers/ShortestRemainingTimeScheduler.h
new file mode 100644
index 00000000..15265985
--- /dev/null
+++ b/Simulator/include/simulation/schedulers/ShortestRemainingTimeScheduler.h
@@ -0,0 +1,46 @@
+#pragma once
+#include "Scheduler.h"
+#include <algorithm>
+
+namespace Simulation
+{
+ class ShortestRemainingTimeScheduler : public Scheduler
+ {
+ protected:
+ ~ShortestRemainingTimeScheduler()
+ {
+ }
+
+ public:
+ /*
+ Distribute workloads according to the srtf principle
+ */
+ void schedule(std::vector<std::reference_wrapper<Modeling::Machine>>& machines, std::vector<Workload*> workloads) override
+ {
+ if (workloads.size() == 0)
+ return;
+
+ std::sort(
+ workloads.begin(),
+ workloads.end(),
+ [](Workload* a, Workload* b) -> bool {
+ return a->getRemainingOperations() < b->getRemainingOperations();
+ }
+ );
+
+ int taskIndex = 0;
+
+ std::for_each(
+ machines.begin(),
+ machines.end(),
+ [&workloads, &taskIndex](Modeling::Machine& machine) {
+ while (!workloads.at(taskIndex)->dependencyFinished)
+ taskIndex = (++taskIndex) % workloads.size();
+
+ machine.giveTask(workloads.at(taskIndex));
+ taskIndex = (++taskIndex) % workloads.size();
+ }
+ );
+ }
+ };
+}
diff --git a/Simulator/include/simulation/workloads/Workload.h b/Simulator/include/simulation/workloads/Workload.h
new file mode 100644
index 00000000..9de57990
--- /dev/null
+++ b/Simulator/include/simulation/workloads/Workload.h
@@ -0,0 +1,80 @@
+#pragma once
+#include <stdint.h>
+
+namespace Simulation
+{
+ /*
+ The Workload class models a workload.
+ */
+ class Workload
+ {
+ public:
+ /*
+ Initializes the TOTAL_FLOPS and the remainingFlops to the size.
+ */
+ Workload(int size, int startTick, int dbId, int traceId, int dependency);
+
+ /*
+ Decreases the remainingFlops by the given amount.
+ */
+ void doOperations(uint32_t opCount);
+
+ /*
+ Returns the amount of operations left to do.
+ */
+ uint32_t getRemainingOperations() const;
+
+ /*
+ Returns the total amount of operations, including finished ones.
+ */
+ uint32_t getTotalOperations() const;
+
+ /*
+ Returns true if the workload has been finished.
+ */
+ bool isFinished() const;
+
+ /*
+ Returns the id of this workload.
+ */
+ uint32_t getId() const;
+
+ /*
+ Returns the dependency id of this workload.
+ */
+ int getDependencyId() const;
+
+ /**
+ * \return The start tick of this workload.
+ */
+ uint32_t getStartTick() const
+ {
+ return START_TICK;
+ }
+
+ // True if the dependency of this workload has finished.
+ bool dependencyFinished = false;
+
+ private:
+ // The id of the workload this workload depends on.
+ int dependencyId;
+
+ // Finished is true if the remainingFlops is 0.
+ bool finished = false;
+
+ // The amount of operations done.
+ uint32_t remainingFlops;
+
+ // The total amount of operations required to finish this task.
+ uint32_t TOTAL_FLOPS;
+
+ // The tick during which this workload was started.
+ uint32_t START_TICK;
+
+ // The id of this workload in the database
+ uint32_t ID;
+
+ // The id of the trace this workload belongs to in the database.
+ uint32_t TRACE_ID;
+ };
+}
diff --git a/Simulator/include/simulation/workloads/WorkloadPool.h b/Simulator/include/simulation/workloads/WorkloadPool.h
new file mode 100644
index 00000000..28a2ad04
--- /dev/null
+++ b/Simulator/include/simulation/workloads/WorkloadPool.h
@@ -0,0 +1,43 @@
+#pragma once
+#include "simulation/workloads/Workload.h"
+#include <vector>
+
+namespace Simulation
+{
+ class WorkloadPool
+ {
+ public:
+ /*
+ Adds the given workload to this pool of workloads.
+ */
+ void addWorkload(Workload w);
+
+ /*
+ Returns a reference to the vector of workloads.
+ */
+ std::vector<Workload*> getWorkloads(uint32_t currentTick);
+
+ /*
+ Returns a reference to the workload with the given id.
+ */
+ Workload& getWorkload(int id);
+
+ /*
+ Removes all workloads that are finished.
+ */
+ void clearFinishedWorkloads();
+
+ /*
+ Returns true if the workloads vector of this pool is empty.
+ */
+ bool isEmpty();
+
+ private:
+ /*
+ Sets all dependencyFinished to true of workloads with the given id as dependency.
+ */
+ void setDependenciesFinished(int id);
+
+ std::vector<Workload> workloads;
+ };
+}