gem5 [DEVELOP-FOR-25.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, std::string link_name)
70 : Consumer(em, Switch::THROTTLE_EV_PRI),
71 m_switch_id(sID), m_switch(em), m_node(node),
75{
76 m_vnets = 0;
77
78 m_link_latency = link_latency;
79 m_endpoint_bandwidth = endpoint_bandwidth;
80
82}
83
84Throttle::Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency,
85 int link_bandwidth_multiplier, int endpoint_bandwidth,
86 Switch *em, std::string link_name)
87 : Throttle(sID, rs, node, link_latency, endpoint_bandwidth, em, link_name)
88{
89 gem5_assert(link_bandwidth_multiplier > 0);
90 m_link_bandwidth_multiplier.push_back(link_bandwidth_multiplier);
91}
92
93Throttle::Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency,
94 const std::vector<int> &vnet_channels,
95 const std::vector<int> &vnet_bandwidth_multiplier,
96 int endpoint_bandwidth, Switch *em, std::string link_name)
97 : Throttle(sID, rs, node, link_latency, endpoint_bandwidth, em, link_name)
98{
99 m_physical_vnets = true;
100 for (auto link_bandwidth_multiplier : vnet_bandwidth_multiplier){
101 gem5_assert(link_bandwidth_multiplier > 0);
102 m_link_bandwidth_multiplier.push_back(link_bandwidth_multiplier);
103 }
104 for (auto channels : vnet_channels){
105 gem5_assert(channels > 0);
106 m_vnet_channels.push_back(channels);
107 }
109}
110
111void
113 const std::vector<MessageBuffer*>& out_vec)
114{
115 assert(in_vec.size() == out_vec.size());
116
117 for (int vnet = 0; vnet < in_vec.size(); ++vnet) {
118 MessageBuffer *in_ptr = in_vec[vnet];
119 MessageBuffer *out_ptr = out_vec[vnet];
120
121 m_units_remaining.emplace_back(getChannelCnt(vnet),0);
122 m_in.push_back(in_ptr);
123 m_out.push_back(out_ptr);
124
125 // Set consumer and description
126 in_ptr->setConsumer(this);
127 std::string desc = "[Queue to Throttle " +
128 std::to_string(m_switch_id) + " " + std::to_string(m_node) + "]";
129 }
130
131 m_vnets = in_vec.size();
132
135 (m_link_bandwidth_multiplier.size() == 1));
136}
137
138int
140{
141 int bw = m_physical_vnets ?
144 gem5_assert(bw > 0);
145 return m_endpoint_bandwidth * bw;
146}
147
148int
150{
151 int sum = getLinkBandwidth(0) * getChannelCnt(0);
152 if (m_physical_vnets) {
153 for (unsigned i = 1; i < m_vnets; ++i)
155 }
156 return sum;
157}
158
159int
161{
162 return m_physical_vnets ? m_vnet_channels[vnet] : 1;
163}
164
165void
166Throttle::operateVnet(int vnet, int channel, int &total_bw_remaining,
167 bool &bw_saturated, bool &output_blocked,
169{
170 if (out == nullptr || in == nullptr) {
171 return;
172 }
173
174 int &units_remaining = m_units_remaining[vnet][channel];
175
176 gem5_assert(units_remaining >= 0);
177 Tick current_time = m_switch->clockEdge();
178
179 int bw_remaining = m_physical_vnets ?
180 getLinkBandwidth(vnet) : total_bw_remaining;
181
182 auto hasPendingWork = [&]{ return in->isReady(current_time) ||
183 units_remaining > 0; };
184 while ((bw_remaining > 0) && hasPendingWork() &&
185 out->areNSlotsAvailable(1, current_time)) {
186 // See if we are done transferring the previous message on
187 // this virtual network
188 if (units_remaining == 0 && in->isReady(current_time)) {
189 // Find the size of the message we are moving
190 MsgPtr msg_ptr = in->peekMsgPtr();
191 Message *net_msg_ptr = msg_ptr.get();
192 Tick msg_enqueue_time = msg_ptr->getLastEnqueueTime();
193 units_remaining = network_message_to_size(net_msg_ptr);
194
195 DPRINTF(RubyNetwork, "throttle: %d my bw %d bw spent "
196 "enqueueing net msg %d time: %lld.\n",
197 m_node, getLinkBandwidth(vnet), units_remaining,
198 m_ruby_system->curCycle());
199
200 // Move the message
201 in->dequeue(current_time);
202 out->enqueue(msg_ptr, current_time,
203 m_switch->cyclesToTicks(m_link_latency),
204 m_ruby_system->getRandomization(),
205 m_ruby_system->getWarmupEnabled());
206
207 // Count the message
208 (*(throttleStats.
209 msg_counts[net_msg_ptr->getMessageSize()]))[vnet]++;
210 throttleStats.total_msg_count += 1;
211 uint32_t total_size =
213 throttleStats.total_msg_bytes += total_size;
214 total_size -=
215 Network::MessageSizeType_to_int(MessageSizeType_Control);
216 throttleStats.total_data_msg_bytes += total_size;
217 throttleStats.total_msg_wait_time +=
218 current_time - msg_enqueue_time;
219 DPRINTF(RubyNetwork, "%s\n", *out);
220 }
221
222 // Calculate the amount of bandwidth we spent on this message
223 int spent = std::min(units_remaining, bw_remaining);
224 units_remaining -= spent;
225 bw_remaining -= spent;
226 total_bw_remaining -= spent;
227 }
228
229 gem5_assert(units_remaining >= 0);
230 gem5_assert(bw_remaining >= 0);
231 gem5_assert(total_bw_remaining >= 0);
232
233 // Notify caller if
234 // - we ran out of bandwith and still have stuff to do
235 // - we had something to do but output queue was unavailable
236 if (hasPendingWork()) {
237 gem5_assert((bw_remaining == 0) ||
238 !out->areNSlotsAvailable(1, current_time));
239 bw_saturated = bw_saturated || (bw_remaining == 0);
240 output_blocked = output_blocked ||
241 !out->areNSlotsAvailable(1, current_time);
242 }
243}
244
245void
247{
248 // Limits the number of message sent to a limited number of bytes/cycle.
249 assert(getTotalLinkBandwidth() > 0);
250 int bw_remaining = getTotalLinkBandwidth();
251
253 bool bw_saturated = false;
254 bool output_blocked = false;
255
256 // variable for deciding the direction in which to iterate
257 bool iteration_direction = false;
258
259
260 // invert priorities to avoid starvation seen in the component network
263 iteration_direction = true;
264 }
265
266 if (iteration_direction) {
267 for (int vnet = 0; vnet < m_vnets; ++vnet) {
268 for (int channel = 0; channel < getChannelCnt(vnet); ++channel) {
269 operateVnet(vnet, channel, bw_remaining,
270 bw_saturated, output_blocked,
271 m_in[vnet], m_out[vnet]);
272 }
273 }
274 } else {
275 for (int vnet = m_vnets-1; vnet >= 0; --vnet) {
276 for (int channel = 0; channel < getChannelCnt(vnet); ++channel) {
277 operateVnet(vnet, channel, bw_remaining,
278 bw_saturated, output_blocked,
279 m_in[vnet], m_out[vnet]);
280 }
281 }
282 }
283
284 // We should only wake up when we use the bandwidth
285 // This is only mostly true
286 // assert(bw_remaining != getLinkBandwidth());
287
288 // Record that we used some or all of the link bandwidth this cycle
289 double ratio = 1.0 - (double(bw_remaining) /
290 double(getTotalLinkBandwidth()));
291
292 // If ratio = 0, we used no bandwidth, if ratio = 1, we used all
293 throttleStats.acc_link_utilization += ratio;
294
295 if (bw_saturated) throttleStats.total_bw_sat_cy += 1;
296 if (output_blocked) throttleStats.total_stall_cy += 1;
297
298 if (bw_saturated || output_blocked) {
299 // We are out of bandwidth for this cycle, so wakeup next
300 // cycle and continue
301 DPRINTF(RubyNetwork, "%s scheduled again\n", *this);
303 }
304}
305
306void
307Throttle::print(std::ostream& out) const
308{
309 ccprintf(out, "[%i bw:", m_node);
310 if (m_physical_vnets) {
311 for (unsigned i = 0; i < m_vnets; ++i)
312 ccprintf(out, " vnet%d=%i", i, getLinkBandwidth(i));
313 } else {
314 ccprintf(out, " %i", getTotalLinkBandwidth());
315 }
316 ccprintf(out, "]");
317}
318
319int
321{
322 assert(net_msg_ptr != NULL);
323
324 int size = Network::MessageSizeType_to_int(net_msg_ptr->getMessageSize());
326
327 // Artificially increase the size of broadcast messages
328 if (BROADCAST_SCALING > 1 && net_msg_ptr->getDestination().isBroadcast())
329 size *= BROADCAST_SCALING;
330
331 return size;
332}
333
336 Switch *parent, const NodeID &nodeID, std::string link_name
337) : statistics::Group(parent, csprintf("throttle%02i", nodeID).c_str()),
339 csprintf("Accumulated link utilization %s",link_name).c_str()),
341 "Average link utilization"),
343 "Total number of messages forwarded by this switch"),
345 "Total number of bytes forwarded by this switch"),
347 "Total number of data bytes forwarded by this switch"),
349 "Total time spend forwarding messages"),
350 ADD_STAT(total_stall_cy, statistics::units::Cycle::get(),
351 "Total time spent blocked on any output link"),
353 "Total time bandwidth was saturated on any output link"),
355 "Average time a message took to be forwarded"),
356 ADD_STAT(avg_bandwidth, statistics::units::Ratio::get(),
357 "Average bandwidth (GB/s)"),
359 "Average useful (only data) bandwidth (GB/s)")
360{
362 (simTicks / parent->clockPeriod());
363
365
366 avg_bandwidth.precision(2);
368 statistics::constant(1024*1024*1024);
369
370 avg_useful_bandwidth.precision(2);
372 statistics::constant(1024*1024*1024);
373
374 for (MessageSizeType type = MessageSizeType_FIRST;
375 type < MessageSizeType_NUM; ++type) {
376 msg_counts[(unsigned int)type] =
377 new statistics::Vector(this,
378 csprintf("msg_count.%s", MessageSizeType_to_string(type)).c_str());
379 msg_counts[(unsigned int)type]
381 .flags(statistics::nozero)
382 ;
383
384 msg_bytes[(unsigned int) type] =
385 new statistics::Formula(this,
386 csprintf("msg_bytes.%s", MessageSizeType_to_string(type)).c_str());
387 msg_bytes[(unsigned int) type]
388 ->flags(statistics::nozero)
389 ;
390
391 *(msg_bytes[(unsigned int) type]) =
394 }
395}
396
397} // namespace ruby
398} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
Tick clockPeriod() const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
Consumer(ClockedObject *em, Event::Priority ev_prio=Event::Default_Pri)
Definition Consumer.cc:49
void scheduleEvent(Cycles timeDelta)
Definition Consumer.cc:56
ClockedObject * em
Definition Consumer.hh:93
void setConsumer(Consumer *consumer)
bool areNSlotsAvailable(unsigned int n, Tick curTime)
bool isReady(Tick current_time) const
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
void enqueue(MsgPtr message, Tick curTime, Tick delta, bool ruby_is_random, bool ruby_warmup, bool bypassStrictFIFO=false)
virtual const NetDest & getDestination() const
Definition Message.hh:115
virtual const MessageSizeType & getMessageSize() const
Definition Message.hh:79
bool isBroadcast() const
Definition NetDest.cc:200
static uint32_t getNumberOfVirtualNetworks()
Definition Network.hh:91
static uint32_t MessageSizeType_to_int(MessageSizeType size_type)
Definition Network.cc:166
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:166
std::vector< std::vector< int > > m_units_remaining
Definition Throttle.hh:122
void print(std::ostream &out) const
Definition Throttle.cc:307
const int m_switch_id
Definition Throttle.hh:124
int getTotalLinkBandwidth() const
Definition Throttle.cc:149
std::string link_name
Definition Throttle.hh:136
Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency, int endpoint_bandwidth, Switch *em, std::string link_name)
Definition Throttle.cc:68
RubySystem * m_ruby_system
Definition Throttle.hh:134
gem5::ruby::Throttle::ThrottleStats throttleStats
std::vector< MessageBuffer * > m_out
Definition Throttle.hh:120
int getLinkBandwidth(int vnet) const
Definition Throttle.cc:139
void addLinks(const std::vector< MessageBuffer * > &in_vec, const std::vector< MessageBuffer * > &out_vec)
Definition Throttle.cc:112
std::vector< int > m_link_bandwidth_multiplier
Definition Throttle.hh:129
int getChannelCnt(int vnet) const
Definition Throttle.cc:160
A formula for statistics that is calculated when printed.
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:349
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 9, 8 > rs
Bitfield< 18 > sum
Definition misc.hh:1235
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:320
Units for Stats.
Definition units.hh:113
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 Arm Limited 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:150
statistics::Formula avg_msg_wait_time
Definition Throttle.hh:155
statistics::Formula link_utilization
Definition Throttle.hh:145
statistics::Formula * msg_bytes[MessageSizeType_NUM]
Definition Throttle.hh:147
statistics::Scalar total_msg_wait_time
Definition Throttle.hh:152
statistics::Scalar total_data_msg_bytes
Definition Throttle.hh:151
statistics::Scalar acc_link_utilization
Definition Throttle.hh:144
ThrottleStats(Switch *parent, const NodeID &nodeID, std::string link_name)
Definition Throttle.cc:335
statistics::Formula avg_useful_bandwidth
Definition Throttle.hh:157
statistics::Scalar total_msg_count
Definition Throttle.hh:149
statistics::Formula avg_bandwidth
Definition Throttle.hh:156
statistics::Vector * msg_counts[MessageSizeType_NUM]
Definition Throttle.hh:146
statistics::Scalar total_stall_cy
Definition Throttle.hh:153
statistics::Scalar total_bw_sat_cy
Definition Throttle.hh:154

Generated on Mon May 26 2025 09:19:12 for gem5 by doxygen 1.13.2