1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
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;
};
}
|