gem5 v24.0.0.0
Loading...
Searching...
No Matches
Throttle.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
42
43#include <cassert>
44
45#include "base/cast.hh"
46#include "base/cprintf.hh"
47#include "debug/RubyNetwork.hh"
53#include "sim/stats.hh"
54
55namespace gem5
56{
57
58namespace ruby
59{
60
61const int MESSAGE_SIZE_MULTIPLIER = 1000;
62//const int BROADCAST_SCALING = 4; // Have a 16p system act like a 64p systems
63const int BROADCAST_SCALING = 1;
64const int PRIORITY_SWITCH_LIMIT = 128;
65
66static int network_message_to_size(Message* net_msg_ptr);
67
68Throttle::Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency,
69 int endpoint_bandwidth, Switch *em)
70 : Consumer(em, Switch::THROTTLE_EV_PRI),
71 m_switch_id(sID), m_switch(em), m_node(node),
72 m_physical_vnets(false), m_ruby_system(rs),
73 throttleStats(em, node)
74{
75 m_vnets = 0;
76
77 m_link_latency = link_latency;
78 m_endpoint_bandwidth = endpoint_bandwidth;
79
81}
82
83Throttle::Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency,
84 int link_bandwidth_multiplier, int endpoint_bandwidth,
85 Switch *em)
86 : Throttle(sID, rs, node, link_latency, endpoint_bandwidth, em)
87{
88 gem5_assert(link_bandwidth_multiplier > 0);
89 m_link_bandwidth_multiplier.push_back(link_bandwidth_multiplier);
90}
91
92Throttle::Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency,
93 const std::vector<int> &vnet_channels,
94 const std::vector<int> &vnet_bandwidth_multiplier,
95 int endpoint_bandwidth, Switch *em)
96 : Throttle(sID, rs, node, link_latency, endpoint_bandwidth, em)
97{
98 m_physical_vnets = true;
99 for (auto link_bandwidth_multiplier : vnet_bandwidth_multiplier){
100 gem5_assert(link_bandwidth_multiplier > 0);
101 m_link_bandwidth_multiplier.push_back(link_bandwidth_multiplier);
102 }
103 for (auto channels : vnet_channels){
104 gem5_assert(channels > 0);
105 m_vnet_channels.push_back(channels);
106 }
108}
109
110void
112 const std::vector<MessageBuffer*>& out_vec)
113{
114 assert(in_vec.size() == out_vec.size());
115
116 for (int vnet = 0; vnet < in_vec.size(); ++vnet) {
117 MessageBuffer *in_ptr = in_vec[vnet];
118 MessageBuffer *out_ptr = out_vec[vnet];
119
120 m_units_remaining.emplace_back(getChannelCnt(vnet),0);
121 m_in.push_back(in_ptr);
122 m_out.push_back(out_ptr);
123
124 // Set consumer and description
125 in_ptr->setConsumer(this);
126 std::string desc = "[Queue to Throttle " +
127 std::to_string(m_switch_id) + " " + std::to_string(m_node) + "]";
128 }
129
130 m_vnets = in_vec.size();
131
134 (m_link_bandwidth_multiplier.size() == 1));
135}
136
137int
139{
140 int bw = m_physical_vnets ?
143 gem5_assert(bw > 0);
144 return m_endpoint_bandwidth * bw;
145}
146
147int
149{
150 int sum = getLinkBandwidth(0) * getChannelCnt(0);
151 if (m_physical_vnets) {
152 for (unsigned i = 1; i < m_vnets; ++i)
154 }
155 return sum;
156}
157
158int
160{
161 return m_physical_vnets ? m_vnet_channels[vnet] : 1;
162}
163
164void
165Throttle::operateVnet(int vnet, int channel, int &total_bw_remaining,
166 bool &bw_saturated, bool &output_blocked,
168{
169 if (out == nullptr || in == nullptr) {
170 return;
171 }
172
173 int &units_remaining = m_units_remaining[vnet][channel];
174
175 gem5_assert(units_remaining >= 0);
176 Tick current_time = m_switch->clockEdge();
177
178 int bw_remaining = m_physical_vnets ?
179 getLinkBandwidth(vnet) : total_bw_remaining;
180
181 auto hasPendingWork = [&]{ return in->isReady(current_time) ||
182 units_remaining > 0; };
183 while ((bw_remaining > 0) && hasPendingWork() &&
184 out->areNSlotsAvailable(1, current_time)) {
185 // See if we are done transferring the previous message on
186 // this virtual network
187 if (units_remaining == 0 && in->isReady(current_time)) {
188 // Find the size of the message we are moving
189 MsgPtr msg_ptr = in->peekMsgPtr();
190 Message *net_msg_ptr = msg_ptr.get();
191 Tick msg_enqueue_time = msg_ptr->getLastEnqueueTime();
192 units_remaining = network_message_to_size(net_msg_ptr);
193
194 DPRINTF(RubyNetwork, "throttle: %d my bw %d bw spent "
195 "enqueueing net msg %d time: %lld.\n",
196 m_node, getLinkBandwidth(vnet), units_remaining,
198
199 // Move the message
200 in->dequeue(current_time);
201 out->enqueue(msg_ptr, current_time,
203
204 // Count the message
205 (*(throttleStats.
206 msg_counts[net_msg_ptr->getMessageSize()]))[vnet]++;
208 uint32_t total_size =
210 throttleStats.total_msg_bytes += total_size;
211 total_size -=
212 Network::MessageSizeType_to_int(MessageSizeType_Control);
215 current_time - msg_enqueue_time;
216 DPRINTF(RubyNetwork, "%s\n", *out);
217 }
218
219 // Calculate the amount of bandwidth we spent on this message
220 int spent = std::min(units_remaining, bw_remaining);
221 units_remaining -= spent;
222 bw_remaining -= spent;
223 total_bw_remaining -= spent;
224 }
225
226 gem5_assert(units_remaining >= 0);
227 gem5_assert(bw_remaining >= 0);
228 gem5_assert(total_bw_remaining >= 0);
229
230 // Notify caller if
231 // - we ran out of bandwith and still have stuff to do
232 // - we had something to do but output queue was unavailable
233 if (hasPendingWork()) {
234 gem5_assert((bw_remaining == 0) ||
235 !out->areNSlotsAvailable(1, current_time));
236 bw_saturated = bw_saturated || (bw_remaining == 0);
237 output_blocked = output_blocked ||
238 !out->areNSlotsAvailable(1, current_time);
239 }
240}
241
242void
244{
245 // Limits the number of message sent to a limited number of bytes/cycle.
246 assert(getTotalLinkBandwidth() > 0);
247 int bw_remaining = getTotalLinkBandwidth();
248
250 bool bw_saturated = false;
251 bool output_blocked = false;
252
253 // variable for deciding the direction in which to iterate
254 bool iteration_direction = false;
255
256
257 // invert priorities to avoid starvation seen in the component network
260 iteration_direction = true;
261 }
262
263 if (iteration_direction) {
264 for (int vnet = 0; vnet < m_vnets; ++vnet) {
265 for (int channel = 0; channel < getChannelCnt(vnet); ++channel) {
266 operateVnet(vnet, channel, bw_remaining,
267 bw_saturated, output_blocked,
268 m_in[vnet], m_out[vnet]);
269 }
270 }
271 } else {
272 for (int vnet = m_vnets-1; vnet >= 0; --vnet) {
273 for (int channel = 0; channel < getChannelCnt(vnet); ++channel) {
274 operateVnet(vnet, channel, bw_remaining,
275 bw_saturated, output_blocked,
276 m_in[vnet], m_out[vnet]);
277 }
278 }
279 }
280
281 // We should only wake up when we use the bandwidth
282 // This is only mostly true
283 // assert(bw_remaining != getLinkBandwidth());
284
285 // Record that we used some or all of the link bandwidth this cycle
286 double ratio = 1.0 - (double(bw_remaining) /
287 double(getTotalLinkBandwidth()));
288
289 // If ratio = 0, we used no bandwidth, if ratio = 1, we used all
291
292 if (bw_saturated) throttleStats.total_bw_sat_cy += 1;
293 if (output_blocked) throttleStats.total_stall_cy += 1;
294
295 if (bw_saturated || output_blocked) {
296 // We are out of bandwidth for this cycle, so wakeup next
297 // cycle and continue
298 DPRINTF(RubyNetwork, "%s scheduled again\n", *this);
300 }
301}
302
303void
304Throttle::print(std::ostream& out) const
305{
306 ccprintf(out, "[%i bw:", m_node);
307 if (m_physical_vnets) {
308 for (unsigned i = 0; i < m_vnets; ++i)
309 ccprintf(out, " vnet%d=%i", i, getLinkBandwidth(i));
310 } else {
311 ccprintf(out, " %i", getTotalLinkBandwidth());
312 }
313 ccprintf(out, "]");
314}
315
316int
318{
319 assert(net_msg_ptr != NULL);
320
321 int size = Network::MessageSizeType_to_int(net_msg_ptr->getMessageSize());
323
324 // Artificially increase the size of broadcast messages
325 if (BROADCAST_SCALING > 1 && net_msg_ptr->getDestination().isBroadcast())
326 size *= BROADCAST_SCALING;
327
328 return size;
329}
330
332ThrottleStats::ThrottleStats(Switch *parent, const NodeID &nodeID)
333 : statistics::Group(parent, csprintf("throttle%02i", nodeID).c_str()),
334 ADD_STAT(acc_link_utilization, statistics::units::Count::get(),
335 "Accumulated link utilization"),
336 ADD_STAT(link_utilization, statistics::units::Ratio::get(),
337 "Average link utilization"),
338 ADD_STAT(total_msg_count, statistics::units::Count::get(),
339 "Total number of messages forwarded by this switch"),
340 ADD_STAT(total_msg_bytes, statistics::units::Byte::get(),
341 "Total number of bytes forwarded by this switch"),
342 ADD_STAT(total_data_msg_bytes, statistics::units::Byte::get(),
343 "Total number of data bytes forwarded by this switch"),
344 ADD_STAT(total_msg_wait_time, statistics::units::Tick::get(),
345 "Total time spend forwarding messages"),
346 ADD_STAT(total_stall_cy, statistics::units::Cycle::get(),
347 "Total time spent blocked on any output link"),
348 ADD_STAT(total_bw_sat_cy, statistics::units::Cycle::get(),
349 "Total time bandwidth was saturated on any output link"),
350 ADD_STAT(avg_msg_wait_time, statistics::units::Ratio::get(),
351 "Average time a message took to be forwarded"),
352 ADD_STAT(avg_bandwidth, statistics::units::Ratio::get(),
353 "Average bandwidth (GB/s)"),
354 ADD_STAT(avg_useful_bandwidth, statistics::units::Ratio::get(),
355 "Average usefull (only data) bandwidth (GB/s)")
356{
358 (simTicks / parent->clockPeriod());
359
361
364 statistics::constant(1024*1024*1024);
365
368 statistics::constant(1024*1024*1024);
369
370 for (MessageSizeType type = MessageSizeType_FIRST;
371 type < MessageSizeType_NUM; ++type) {
372 msg_counts[(unsigned int)type] =
373 new statistics::Vector(this,
374 csprintf("msg_count.%s", MessageSizeType_to_string(type)).c_str());
375 msg_counts[(unsigned int)type]
378 ;
379
380 msg_bytes[(unsigned int) type] =
381 new statistics::Formula(this,
382 csprintf("msg_bytes.%s", MessageSizeType_to_string(type)).c_str());
383 msg_bytes[(unsigned int) type]
385 ;
386
387 *(msg_bytes[(unsigned int) type]) =
390 }
391}
392
393} // namespace ruby
394} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Tick cyclesToTicks(Cycles c) const
Tick clockPeriod() const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
void scheduleEvent(Cycles timeDelta)
Definition Consumer.cc:56
void setConsumer(Consumer *consumer)
bool areNSlotsAvailable(unsigned int n, Tick curTime)
bool isReady(Tick current_time) const
void enqueue(MsgPtr message, Tick curTime, Tick delta, bool bypassStrictFIFO=false)
Tick dequeue(Tick current_time, bool decrement_messages=true)
Updates the delay cycles of the message at the head of the queue, removes it from the queue and retur...
const MsgPtr & peekMsgPtr() const
virtual const NetDest & getDestination() const
Definition Message.hh:114
Tick getLastEnqueueTime() const
Definition Message.hh:107
virtual const MessageSizeType & getMessageSize() const
Definition Message.hh:78
bool isBroadcast() const
Definition NetDest.cc:174
static uint32_t getNumberOfVirtualNetworks()
Definition Network.hh:90
static uint32_t MessageSizeType_to_int(MessageSizeType size_type)
Definition Network.cc:164
std::vector< int > m_vnet_channels
Definition Throttle.hh:130
std::vector< MessageBuffer * > m_in
Definition Throttle.hh:119
unsigned int m_vnets
Definition Throttle.hh:121
void operateVnet(int vnet, int channel, int &total_bw_remaining, bool &bw_saturated, bool &output_blocked, MessageBuffer *in, MessageBuffer *out)
Definition Throttle.cc:165
std::vector< std::vector< int > > m_units_remaining
Definition Throttle.hh:122
void print(std::ostream &out) const
Definition Throttle.cc:304
const int m_switch_id
Definition Throttle.hh:124
int getTotalLinkBandwidth() const
Definition Throttle.cc:148
RubySystem * m_ruby_system
Definition Throttle.hh:134
gem5::ruby::Throttle::ThrottleStats throttleStats
Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency, int endpoint_bandwidth, Switch *em)
Definition Throttle.cc:68
std::vector< MessageBuffer * > m_out
Definition Throttle.hh:120
int getLinkBandwidth(int vnet) const
Definition Throttle.cc:138
void addLinks(const std::vector< MessageBuffer * > &in_vec, const std::vector< MessageBuffer * > &out_vec)
Definition Throttle.cc:111
std::vector< int > m_link_bandwidth_multiplier
Definition Throttle.hh:129
int getChannelCnt(int vnet) const
Definition Throttle.cc:159
Derived & precision(int _precision)
Set the precision and marks this stat to print at the end of simulation.
A formula for statistics that is calculated when printed.
Statistics container.
Definition group.hh:93
A vector of scalar stats.
STL vector class.
Definition stl.hh:37
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
#define gem5_assert(cond,...)
The assert macro will function like a normal assert, but will use panic instead of straight abort().
Definition logging.hh:317
uint8_t flags
Definition helpers.cc:87
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 9, 8 > rs
Bitfield< 18 > sum
Definition misc.hh:1198
Bitfield< 2 > em
Definition misc.hh:617
std::shared_ptr< Message > MsgPtr
Definition Message.hh:60
unsigned int NodeID
const int PRIORITY_SWITCH_LIMIT
const int MESSAGE_SIZE_MULTIPLIER
Definition Throttle.cc:61
const int BROADCAST_SCALING
Definition Throttle.cc:63
static int network_message_to_size(Message *net_msg_ptr)
Definition Throttle.cc:317
const FlagsType init
This Stat is Initialized.
Definition info.hh:55
const FlagsType nozero
Don't print if this is zero.
Definition info.hh:67
Temp constant(T val)
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t Tick
Tick count type.
Definition types.hh:58
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
statistics::Value & simTicks
Definition stats.cc:46
statistics::Formula & simSeconds
Definition stats.cc:45
void ccprintf(cp::Print &print)
Definition cprintf.hh:130
statistics::Scalar total_msg_bytes
Definition Throttle.hh:147
statistics::Formula avg_msg_wait_time
Definition Throttle.hh:152
statistics::Formula link_utilization
Definition Throttle.hh:142
statistics::Formula * msg_bytes[MessageSizeType_NUM]
Definition Throttle.hh:144
statistics::Scalar total_msg_wait_time
Definition Throttle.hh:149
statistics::Scalar total_data_msg_bytes
Definition Throttle.hh:148
statistics::Scalar acc_link_utilization
Definition Throttle.hh:141
ThrottleStats(Switch *parent, const NodeID &nodeID)
Definition Throttle.cc:332
statistics::Formula avg_useful_bandwidth
Definition Throttle.hh:154
statistics::Scalar total_msg_count
Definition Throttle.hh:146
statistics::Formula avg_bandwidth
Definition Throttle.hh:153
statistics::Vector * msg_counts[MessageSizeType_NUM]
Definition Throttle.hh:143
statistics::Scalar total_stall_cy
Definition Throttle.hh:150
statistics::Scalar total_bw_sat_cy
Definition Throttle.hh:151

Generated on Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0