From dab223757258de670c8b41b829ff546c064a3fd5 Mon Sep 17 00:00:00 2001 From: "Thanh C. Tran" Date: Tue, 16 May 2017 01:38:53 +0200 Subject: [PATCH] First try to form multiple ready batches --- .../src/controller/scheduler/SMS.cpp | 194 +++++++++++++++++- .../simulator/src/controller/scheduler/SMS.h | 9 +- 2 files changed, 198 insertions(+), 5 deletions(-) diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp index 24022e1c..ba1d2199 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp @@ -72,6 +72,48 @@ void SMS::batchScheduler() } } +/** + * Pick a Thread according to Shortest-Job Policy + * Save the picked one into lastSelectedThread + * @return true if it can, otherwise false + */ +bool SMS::pickSJF() +{ + // find threads with non-empty request buffers + std::vector threadsWithNonEmptyRequestBuffer; + for (auto& requestBuffer : requestBuffers) + { + if (!requestBuffer.second.empty()) + { + // marked as thread with non-empty request buffer + threadsWithNonEmptyRequestBuffer.push_back(requestBuffer.first); + } + } + + if (!threadsWithNonEmptyRequestBuffer.empty()) + { + // pick shortest-job thread among threads with non-empty request buffer + Thread minThread = threadsWithNonEmptyRequestBuffer.front(); + for (auto& thread : threadsWithNonEmptyRequestBuffer) + { + if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread]) + { + minThread = thread; + } + } + + // save selected thread + lastSelectedThread = readybatches.find(minThread); + debugManager.printDebugMessage(name(), + "[SJF] Select ready batch of thread " + to_string(minThread.ID())); + return true; + } + else + { + return false; + } +} + bool SMS::selectSJF(sc_time memClk) { // find threads with non-empty ready batch @@ -126,7 +168,78 @@ bool SMS::selectSJF(sc_time memClk) // this mean the request buffers are totally empty return false; } +} +/** + * Drain the picked request buffer into bank buffers + * by move request one-by-one from start of the request buffer till last parameter + * @param memClk + * @param last + */ +void SMS::drain(sc_time memClk, std::deque::iterator last) +{ + unsigned int batchSize = std::distance((*lastSelectedThread).second.begin(), last) + 1; + for (unsigned int i = 1; i <= batchSize; i++) + { + Bank bank = DramExtension::getExtension(*((*lastSelectedThread).second.begin())).getBank(); + // if(bankBuffers[bank].size() == Configuration::getInstance().BankBufferSize) + // { + // wait(bankBufferIsNotFull); + // } + wait(memClk); + bankBuffers[bank].emplace_back(*((*lastSelectedThread).second.begin())); + (*lastSelectedThread).second.pop_front(); + + debugManager.printDebugMessage(name(), + "[SJF] Drain request in the ready batch of thread " + + to_string((*lastSelectedThread).first.ID()) + " to bankbuffer " + + to_string(bank.ID())); + } +} + +/** + * Pick a Thread according to Round-Robin Policy + * Save the picked one into lastSelectedThread + * @return true if it can pick one, otherwise false + */ +bool SMS::pickRR() +{ + std::map>::iterator nextSelectedThread; + if (lastSelectedThread == requestBuffers.end()) + { + lastSelectedThread = requestBuffers.begin(); + nextSelectedThread = lastSelectedThread; + } + else + { + nextSelectedThread = lastSelectedThread; + nextSelectedThread++; + if (nextSelectedThread == requestBuffers.end()) + nextSelectedThread = requestBuffers.begin(); + } + + std::map>::iterator savedOriginalNextSelectedThread = nextSelectedThread; + + while ((*nextSelectedThread).second.empty()) + { + nextSelectedThread++; + if (nextSelectedThread == requestBuffers.end()) + { + nextSelectedThread = requestBuffers.begin(); + } + + if (nextSelectedThread == savedOriginalNextSelectedThread) + { + // 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; } bool SMS::selectRR(sc_time memClk) @@ -138,7 +251,7 @@ bool SMS::selectRR(sc_time memClk) // pick the next non-empty ready batch std::map>::iterator nextSelectedThread; - if(lastSelectedThread == readybatches.end()) + if (lastSelectedThread == readybatches.end()) { lastSelectedThread = readybatches.begin(); nextSelectedThread = lastSelectedThread; @@ -147,7 +260,7 @@ bool SMS::selectRR(sc_time memClk) { nextSelectedThread = lastSelectedThread; nextSelectedThread++; - if(nextSelectedThread == readybatches.end()) + if (nextSelectedThread == readybatches.end()) nextSelectedThread = readybatches.begin(); } std::map>::iterator savedOriginalNextSelectedThread = nextSelectedThread; @@ -232,7 +345,7 @@ void SMS::updateMPKCs(sc_time memClk) { if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) { // reset for every 10k clk cycles for (auto& cacheMiss : cacheMisses) { - MPKCs[cacheMiss.first] = 0; + MPKCs[cacheMiss.first] = 0; } debugManager.printDebugMessage(name(), "Reset MKKCs"); } else { @@ -265,7 +378,7 @@ void SMS::batchFormation(sc_time memClk) { } // deem this batch ready if ((firstDifferentRowAccessReqIter != requestBuffer.second.end()) - || isExceededReqBufferSize(requestBuffer.first) + || isExceededReqBufferSize(requestBuffer.first) || isThresholdAgeExceeded(requestBuffer.first, memClk, requestBuffer.second.begin(), firstDifferentRowAccessReqIter)) { do { readybatches[requestBuffer.first].emplace_back(requestBuffer.second.front()); @@ -296,4 +409,77 @@ bool SMS::existReadyBatches() { return false; } +/** + * Form batch from begin iterator parameter of a request buffer + * If this batch is deemed ready, save the iterator pointing to its last element + * @param memClk + * @param begin + * @return true if this batch is ready, otherwise false + */ +bool SMS::batchFormation(sc_time memClk, std::pair> &requestBuffer, + std::deque::iterator beginIter) +{ + if (requestBuffer.second.empty()) + { + return false; + } + if (requestBuffer.second.end() == beginIter) + { + return false; + } + + if (MPKCs[requestBuffer.first] < LOW_MPKC || isSystemLightlyLoaded()) + { + // bypass requests by forming batch with only one request (threshold age is ZERO) + readyBatchesIter[requestBuffer.first].push_back(beginIter); + return true; + } + else + { + // forming batch with FIFO size & threshold age constraints + auto firstDifferentRowAccessReqIter = beginIter; + Row firstRow = DramExtension::getRow(*beginIter); + while (firstDifferentRowAccessReqIter != requestBuffer.second.end() + && DramExtension::getRow(*firstDifferentRowAccessReqIter) == firstRow) + { + firstDifferentRowAccessReqIter++; + } + + // deem this batch ready + if ((firstDifferentRowAccessReqIter != requestBuffer.second.end()) + || isExceededReqBufferSize(requestBuffer.first) + || isThresholdAgeExceeded(requestBuffer.first, memClk, beginIter, + firstDifferentRowAccessReqIter)) + { + firstDifferentRowAccessReqIter--; + readyBatchesIter[requestBuffer.first].push_back(firstDifferentRowAccessReqIter); + debugManager.printDebugMessage(name(), + "Deem batch ready - thread " + to_string(requestBuffer.first.ID())); + return true; + } + else + { + return false; + } + } +} + +void SMS::multiBatchFormation(sc_time memClk) +{ + for (auto& requestBuffer : requestBuffers) + { + bool formed; + do + { + if (readyBatchesIter[requestBuffer.first].empty()) + { + formed = batchFormation(memClk, (std::pair>&)requestBuffer, requestBuffer.second.begin()); + } + else + { + formed = batchFormation(memClk, (std::pair>&)requestBuffer, readyBatchesIter[requestBuffer.first].back() + 1); + } + } while (formed); + } +} diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.h b/DRAMSys/simulator/src/controller/scheduler/SMS.h index ee4afd79..6e4297ba 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.h +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.h @@ -27,7 +27,8 @@ public: SMS(sc_module_name /*_name*/, ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability), debugManager(DebugManager::getInstance()) { // initialize selected thread iterator - lastSelectedThread = readybatches.end(); + lastSelectedThread = readybatches.end(); +// lastSelectedThread = requestBuffers.end(); SC_THREAD(batchScheduler); } SC_HAS_PROCESS(SMS); @@ -45,6 +46,7 @@ private: std::map> requestBuffers; std::map> bankBuffers; std::map> readybatches; + std::map::iterator>> readyBatchesIter; std::map inFlightMemRequestCounter; std::map cacheMisses; @@ -59,6 +61,11 @@ private: bool selectSJF(sc_time memClk); bool selectRR(sc_time memClk); void batchFormation(sc_time memClk); + bool batchFormation(sc_time memClk, std::pair> &requestBuffer, std::deque::iterator beginIter); + void multiBatchFormation(sc_time memClk); + bool pickSJF(); + bool pickRR(); + void drain(sc_time memClk, std::deque::iterator last); bool existLowIntensityThread(); bool isSystemLightlyLoaded();