Tiago Mück has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/41857 )
Change subject: mem-ruby: fixed SimpleNetwork starvation
......................................................................
mem-ruby: fixed SimpleNetwork starvation
The round-robing scheduling seed is shared across all ports and vnets
in the router and it's possible that, under certain heavy traffic
scenarios, the same port will always fill the input buffers before any
other port is checked.
This patch removes the round-robin scheduling. The port to be checked
first is always the one with the oldest message.
JIRA: https://gem5.atlassian.net/browse/GEM5-920
Change-Id: I918694d46faa0abd00ce9180bc98c58a9b5af0b5
Signed-off-by: Tiago Mück <[email protected]>
---
M src/mem/ruby/network/MessageBuffer.cc
M src/mem/ruby/network/MessageBuffer.hh
M src/mem/ruby/network/simple/PerfectSwitch.cc
M src/mem/ruby/network/simple/PerfectSwitch.hh
4 files changed, 51 insertions(+), 25 deletions(-)
diff --git a/src/mem/ruby/network/MessageBuffer.cc
b/src/mem/ruby/network/MessageBuffer.cc
index d67b678..2ecefad 100644
--- a/src/mem/ruby/network/MessageBuffer.cc
+++ b/src/mem/ruby/network/MessageBuffer.cc
@@ -485,6 +485,15 @@
(m_prio_heap.front()->getLastEnqueueTime() <= current_time));
}
+Tick
+MessageBuffer::readyTime() const
+{
+ if (m_prio_heap.empty())
+ return MaxTick;
+ else
+ return m_prio_heap.front()->getLastEnqueueTime();
+}
+
uint32_t
MessageBuffer::functionalAccess(Packet *pkt, bool is_read, WriteMask *mask)
{
diff --git a/src/mem/ruby/network/MessageBuffer.hh
b/src/mem/ruby/network/MessageBuffer.hh
index 4d70f30..16a520b 100644
--- a/src/mem/ruby/network/MessageBuffer.hh
+++ b/src/mem/ruby/network/MessageBuffer.hh
@@ -80,6 +80,9 @@
// TRUE if head of queue timestamp <= SystemTime
bool isReady(Tick current_time) const;
+ // earliest tick the head of queue will be ready, or MaxTick if empty
+ Tick readyTime() const;
+
void
delayHead(Tick current_time, Tick delta)
{
diff --git a/src/mem/ruby/network/simple/PerfectSwitch.cc
b/src/mem/ruby/network/simple/PerfectSwitch.cc
index a821344..38191b5 100644
--- a/src/mem/ruby/network/simple/PerfectSwitch.cc
+++ b/src/mem/ruby/network/simple/PerfectSwitch.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 ARM Limited
+ * Copyright (c) 2020-2021 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@@ -64,7 +64,6 @@
: Consumer(sw, Switch::PERFECTSWITCH_EV_PRI),
m_switch_id(sid), m_switch(sw)
{
- m_round_robin_start = 0;
m_wakeups_wo_switch = 0;
m_virtual_networks = virt_nets;
}
@@ -116,32 +115,28 @@
void
PerfectSwitch::operateVnet(int vnet)
{
- // This is for round-robin scheduling
- int incoming = m_round_robin_start;
- m_round_robin_start++;
- if (m_round_robin_start >= m_in.size()) {
- m_round_robin_start = 0;
- }
-
if (m_pending_message_count[vnet] > 0) {
- // for all input ports, use round robin scheduling
- for (int counter = 0; counter < m_in.size(); counter++) {
- // Round robin scheduling
- incoming++;
- if (incoming >= m_in.size()) {
- incoming = 0;
- }
-
- // Is there a message waiting?
- if (m_in[incoming].size() <= vnet) {
+ // first check the port with the oldest message
+ unsigned incoming = 0;
+ Tick lowest_tick = MaxTick;
+ for (int counter = 0; counter < m_in.size(); ++counter) {
+ MessageBuffer *buffer = inBuffer(counter, vnet);
+ if (buffer == nullptr)
continue;
+ if (buffer->readyTime() < lowest_tick){
+ lowest_tick = buffer->readyTime();
+ incoming = counter;
}
-
- MessageBuffer *buffer = m_in[incoming][vnet];
- if (buffer == nullptr) {
+ }
+ DPRINTF(RubyNetwork, "vnet %d: %d pending msgs. "
+ "Checking port %d first\n",
+ vnet, m_pending_message_count[vnet], incoming);
+ // check all ports starting with the one with the oldest message
+ for (int counter = 0; counter < m_in.size();
+ ++counter, incoming = (incoming + 1) % m_in.size()) {
+ MessageBuffer *buffer = inBuffer(incoming, vnet);
+ if (buffer == nullptr)
continue;
- }
-
operateMessageBuffer(buffer, incoming, vnet);
}
}
diff --git a/src/mem/ruby/network/simple/PerfectSwitch.hh
b/src/mem/ruby/network/simple/PerfectSwitch.hh
index 12d5e46..7f6e36f 100644
--- a/src/mem/ruby/network/simple/PerfectSwitch.hh
+++ b/src/mem/ruby/network/simple/PerfectSwitch.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2021 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved.
*
@@ -99,11 +111,18 @@
std::vector<LinkOrder> m_link_order;
uint32_t m_virtual_networks;
- int m_round_robin_start;
int m_wakeups_wo_switch;
SimpleNetwork* m_network_ptr;
std::vector<int> m_pending_message_count;
+
+ MessageBuffer* inBuffer(int in_port, int vnet)
+ {
+ if (m_in[in_port].size() <= vnet)
+ return nullptr;
+ else
+ return m_in[in_port][vnet];
+ }
};
inline std::ostream&
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/41857
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I918694d46faa0abd00ce9180bc98c58a9b5af0b5
Gerrit-Change-Number: 41857
Gerrit-PatchSet: 1
Gerrit-Owner: Tiago Mück <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s