Optimize with passing const references

This commit is contained in:
Thanh C. Tran
2017-07-16 04:19:51 +02:00
parent 3a3d8162b2
commit 7f9569f25d
4 changed files with 92 additions and 102 deletions

View File

@@ -1,7 +1,7 @@
<mcconfig>
<BankwiseLogic value="0"/>
<OpenPagePolicy value="1" />
<MaxNrOfTransactions value="20" />
<MaxNrOfTransactions value="30" />
<Scheduler value="SMS" />
<SJFProbability value="50" />
<RequestBufferSize value = "10" />
@@ -13,4 +13,4 @@
<!-- Modes: NoStorage, Store (store data without errormodel), ErrorModel (store data with errormodel) -->
<StoreMode value="NoStorage" />
<ControllerCoreDisableRefresh value="0"/>
</mcconfig>
</mcconfig>

View File

@@ -12,14 +12,15 @@
<mcconfig src="sms.xml"/>
<tracesetup id="sms">
<device clkMhz="200">ddr3_example.stl</device>
<!-- <device clkMhz="200">ddr3_example.stl</device>
<device clkMhz="200">sms_t1.stl</device>
<device clkMhz="200">sms_t2.stl</device>
<device clkMhz="200">sms_t3.stl</device>
<device clkMhz="200">sms_t4.stl</device>
<device clkMhz="200">stream.stl</device>
<device clkMhz="200">random.stl</device>
<device clkMhz="200">chstone-adpcm_32.stl</device>
<device clkMhz="200">sms_t4.stl</device>-->
<device clkMhz="1000">random.stl</device>
<device clkMhz="1000">chstone-adpcm_32.stl</device>
<device clkMhz="1000">stream.stl</device>
</tracesetup>
</simulation>

View File

@@ -61,15 +61,13 @@ void SMS::batchScheduler()
multiBatchFormation(memClk);
if (existReadyBatches()) {
if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) {
if (pickSJF()) {
drain(memClk, (*lastSelectedThread).second.front());
(*lastSelectedThread).second.pop_front();
}
pickSJF();
drain(memClk);
(*lastSelectedThread).second.pop_front();
} else {
if (pickRR()) {
drain(memClk, (*lastSelectedThread).second.front());
(*lastSelectedThread).second.pop_front();
}
pickRR();
drain(memClk);
(*lastSelectedThread).second.pop_front();
}
} else {
wait(memClk);
@@ -87,7 +85,7 @@ bool SMS::pickSJF()
{
// find threads with ready batches
std::vector<Thread> threadsWithReadyBatches;
for (auto& each : readyBatchIters)
for (const auto &each : readyBatchIters)
{
if (!each.second.empty())
{
@@ -99,8 +97,8 @@ bool SMS::pickSJF()
if (!threadsWithReadyBatches.empty())
{
// pick shortest-job thread among threads with non-empty request buffer
Thread minThread = threadsWithReadyBatches.front();
for (auto& thread : threadsWithReadyBatches)
Thread &minThread = threadsWithReadyBatches.front();
for (const auto &thread : threadsWithReadyBatches)
{
if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread])
{
@@ -126,17 +124,19 @@ bool SMS::pickSJF()
* @param memClk
* @param last
*/
void SMS::drain(sc_time memClk, std::deque<gp*>::iterator last)
void SMS::drain(const sc_time &memClk)
{
Thread selectedThread = (*lastSelectedThread).first;
if (lastSelectedThread->second.empty()) {
return;
}
const Thread &selectedThread = lastSelectedThread->first;
const std::deque<gp*>::iterator &last = lastSelectedThread->second.front();
assert(last != requestBuffers[selectedThread].end());
unsigned int batchSize = std::distance(requestBuffers[selectedThread].begin(), last) + 1;
assert(batchSize > 0 && batchSize <= requestBuffers[selectedThread].size());
for (unsigned int i = 1; i <= batchSize; i++)
{
Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank();
// if(bankBuffers[bank].size() == Configuration::getInstance().BankBufferSize)
// {
// wait(bankBufferIsNotFull);
// }
wait(memClk);
bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front());
requestBuffers[selectedThread].pop_front();
@@ -155,54 +155,42 @@ void SMS::drain(sc_time memClk, std::deque<gp*>::iterator last)
*/
bool SMS::pickRR()
{
std::map<Thread, std::deque<gp_deque_iterator>>::iterator nextSelectedThread;
if (lastSelectedThread == readyBatchIters.end())
{
lastSelectedThread = readyBatchIters.begin();
nextSelectedThread = lastSelectedThread;
}
else
{
nextSelectedThread = lastSelectedThread;
nextSelectedThread++;
if (nextSelectedThread == readyBatchIters.end())
nextSelectedThread = readyBatchIters.begin();
}
std::map<Thread, std::deque<gp_deque_iterator>>::iterator savedOriginalNextSelectedThread = nextSelectedThread;
while ((*nextSelectedThread).second.empty())
{
nextSelectedThread++;
if (nextSelectedThread == readyBatchIters.end())
if (lastSelectedThread == readyBatchIters.end())
{
nextSelectedThread = readyBatchIters.begin();
lastSelectedThread = readyBatchIters.begin();
if (!(*lastSelectedThread).second.empty()) {
return true;
}
}
if (nextSelectedThread == savedOriginalNextSelectedThread)
std::map<Thread, std::deque<gp_deque_iterator>>::iterator savedOriginalNextSelectedThread = lastSelectedThread;
do
{
// the next thread is the original thread, that mean req buffer are totally empty
// non-existed ready batch to be picked up & drained
return false;
}
}
// save last selected thread
lastSelectedThread = nextSelectedThread;
debugManager.printDebugMessage(name(),
"[RR] Select ready batch of thread " + to_string((*nextSelectedThread).first.ID()));
return true;
lastSelectedThread++;
if (lastSelectedThread == readyBatchIters.end()) {
lastSelectedThread = readyBatchIters.begin();
}
if (lastSelectedThread == savedOriginalNextSelectedThread) {
return false;
}
} while ((*lastSelectedThread).second.empty());
debugManager.printDebugMessage(name(),
"[RR] Select ready batch of thread " + to_string((*lastSelectedThread).first.ID()));
return true;
}
bool SMS::isSystemLightlyLoaded() {
bool SMS::isSystemLightlyLoaded() const {
unsigned int totalRequest = 0;
for (auto& bankBuffer : bankBuffers) {
for (const auto &bankBuffer : bankBuffers) {
totalRequest += bankBuffer.second.size();
}
return (totalRequest <= LOW_SYSTEM_LOAD);
}
bool SMS::existLowIntensityThread() {
for (auto& mpkcPerThread : MPKCs) {
bool SMS::existLowIntensityThread() const {
for (const auto &mpkcPerThread : MPKCs) {
if (mpkcPerThread.second < LOW_MPKC) {
return true;
}
@@ -210,7 +198,7 @@ bool SMS::existLowIntensityThread() {
return false;
}
bool SMS::isThresholdAgeExceeded(Thread thread, sc_time memClk, std::deque<gp*>::iterator begin, std::deque<gp*>::iterator end) {
bool SMS::isThresholdAgeExceeded(const Thread &thread, sc_time const &memClk, std::deque<gp*>::iterator const &begin, std::deque<gp*>::iterator const &end) {
// find the oldest request in the thread's batch
sc_time oldestGenerationTime = sc_time_stamp();
for (auto reqIter = begin; reqIter != end; reqIter++) {
@@ -231,28 +219,28 @@ bool SMS::isThresholdAgeExceeded(Thread thread, sc_time memClk, std::deque<gp*>:
}
}
void SMS::updateMPKCs(sc_time memClk) {
void SMS::updateMPKCs(sc_time const &memClk) {
if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) {
// reset for every 10k clk cycles
for (auto& cacheMiss : cacheMisses) {
for (const auto &cacheMiss : cacheMisses) {
MPKCs[cacheMiss.first] = 0;
}
debugManager.printDebugMessage(name(), "Reset MKKCs");
} else {
// update MPKC for every thread
for (auto& cacheMiss : cacheMisses) {
for (const auto &cacheMiss : cacheMisses) {
MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / (sc_time_stamp());
}
debugManager.printDebugMessage(name(), "Update MPKCs");
}
}
bool SMS::isExceededReqBufferSize(Thread thread) {
bool SMS::isExceededReqBufferSize(Thread const &thread) {
return requestBuffers[thread].size() == Configuration::getInstance().RequestBufferSize;
}
bool SMS::isRequestBuffersEmpty() {
for (auto& requestBuffer : requestBuffers) {
bool SMS::isRequestBuffersEmpty() const {
for (const auto &requestBuffer : requestBuffers) {
if (!requestBuffer.second.empty()) {
return false;
}
@@ -260,8 +248,8 @@ bool SMS::isRequestBuffersEmpty() {
return true;
}
bool SMS::existReadyBatches() {
for (auto& each : readyBatchIters) {
bool SMS::existReadyBatches() const {
for (const auto &each : readyBatchIters) {
if (!each.second.empty()) {
return true;
}
@@ -276,46 +264,47 @@ bool SMS::existReadyBatches() {
* @param begin
* @return true if this batch is ready, otherwise false
*/
bool SMS::batchFormation(sc_time memClk, std::pair<Thread, std::deque<gp*>> &requestBuffer,
std::deque<gp*>::iterator beginIter)
bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque<gp*> const &requestBuffer, std::deque<gp*>::iterator const &beginIter)
{
if (requestBuffer.second.empty())
if (requestBuffer.empty())
{
return false;
}
if (requestBuffer.second.end() == beginIter)
if (requestBuffer.end() == beginIter)
{
return false;
}
if (MPKCs[requestBuffer.first] < LOW_MPKC || isSystemLightlyLoaded())
if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded())
{
// bypass requests by forming batch with only one request (threshold age is ZERO)
readyBatchIters[requestBuffer.first].push_back(beginIter);
readyBatchIters[thread].push_back(beginIter);
return true;
}
else
{
// forming batch with FIFO size & threshold age constraints
auto firstDifferentRowAccessReqIter = beginIter;
std::deque<gp*>::iterator firstDifferentRowAccessReqIter = beginIter;
Row firstRow = DramExtension::getRow(*beginIter);
while (firstDifferentRowAccessReqIter != requestBuffer.second.end()
while (firstDifferentRowAccessReqIter != requestBuffer.end()
&& DramExtension::getRow(*firstDifferentRowAccessReqIter) == firstRow)
{
firstDifferentRowAccessReqIter++;
++firstDifferentRowAccessReqIter;
if (firstDifferentRowAccessReqIter == requestBuffer.end ()) {
break;
}
}
// deem this batch ready
if ((firstDifferentRowAccessReqIter != requestBuffer.second.end())
|| isExceededReqBufferSize(requestBuffer.first)
|| isThresholdAgeExceeded(requestBuffer.first, memClk, beginIter,
firstDifferentRowAccessReqIter))
if ((firstDifferentRowAccessReqIter != requestBuffer.end())
|| isExceededReqBufferSize(thread)
|| isThresholdAgeExceeded(thread, memClk, beginIter, firstDifferentRowAccessReqIter))
{
firstDifferentRowAccessReqIter--;
readyBatchIters[requestBuffer.first].push_back(firstDifferentRowAccessReqIter);
--firstDifferentRowAccessReqIter;
readyBatchIters[thread].push_back(firstDifferentRowAccessReqIter);
debugManager.printDebugMessage(name(),
"Deem batch ready - thread " + to_string(requestBuffer.first.ID()));
"Deem batch ready - thread " + to_string(thread.ID()));
return true;
}
else
@@ -325,29 +314,29 @@ bool SMS::batchFormation(sc_time memClk, std::pair<Thread, std::deque<gp*>> &req
}
}
void SMS::multiBatchFormation(sc_time memClk)
void SMS::multiBatchFormation(sc_time const &memClk)
{
for (auto& requestBuffer : requestBuffers)
for (auto &requestBuffer : requestBuffers)
{
bool formed;
do
{
if (readyBatchIters[requestBuffer.first].empty())
{
formed = batchFormation(memClk, (std::pair<Thread, std::deque<gp*>>&)requestBuffer, requestBuffer.second.begin());
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, requestBuffer.second.begin());
}
else
{
formed = batchFormation(memClk, (std::pair<Thread, std::deque<gp*>>&)requestBuffer, readyBatchIters[requestBuffer.first].back() + 1);
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, readyBatchIters[requestBuffer.first].back() + 1);
}
} while (formed);
} while (!requestBuffer.second.empty() && formed);
}
}
gp* SMS::getPendingRequest(Bank bank)
{
for (auto& requestBuffer : requestBuffers) {
for (auto& request : requestBuffer.second) {
for (const auto &requestBuffer : requestBuffers) {
for (const auto &request : requestBuffer.second) {
if (DramExtension::getBank(request) == bank) {
return request;
}

View File

@@ -65,20 +65,20 @@ private:
DebugManager& debugManager;
bool batchFormation(sc_time memClk, std::pair<Thread, std::deque<gp*>> &requestBuffer, std::deque<gp*>::iterator beginIter);
void multiBatchFormation(sc_time memClk);
bool batchFormation(sc_time const &memClk, Thread const &thread, const std::deque<gp*> &requestBuffer, const std::deque<gp*>::iterator &beginIter);
void multiBatchFormation(const sc_time &memClk);
bool pickSJF();
bool pickRR();
void drain(sc_time memClk, std::deque<gp*>::iterator last);
void drain(const sc_time &memClk);
bool existLowIntensityThread();
bool isSystemLightlyLoaded();
bool isThresholdAgeExceeded(Thread thread, sc_time memClk, std::deque<gp*>::iterator begin, std::deque<gp*>::iterator end);
bool isExceededReqBufferSize(Thread thread);
void updateMPKCs(sc_time memClk);
bool existLowIntensityThread() const;
bool isSystemLightlyLoaded() const;
bool isThresholdAgeExceeded(const Thread &thread, const sc_time &memClk, const std::deque<gp*>::iterator &begin, const std::deque<gp*>::iterator &end);
bool isExceededReqBufferSize(Thread const &thread);
void updateMPKCs(const sc_time &memClk);
bool isRequestBuffersEmpty();
bool existReadyBatches();
bool isRequestBuffersEmpty() const;
bool existReadyBatches() const;
};
#endif // SMS_H