First try to form multiple ready batches

This commit is contained in:
Thanh C. Tran
2017-05-16 01:38:53 +02:00
parent d489db6a46
commit dab2237572
2 changed files with 198 additions and 5 deletions

View File

@@ -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<Thread> 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<gp*>::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<Thread, std::deque<gp*>>::iterator nextSelectedThread;
if (lastSelectedThread == requestBuffers.end())
{
lastSelectedThread = requestBuffers.begin();
nextSelectedThread = lastSelectedThread;
}
else
{
nextSelectedThread = lastSelectedThread;
nextSelectedThread++;
if (nextSelectedThread == requestBuffers.end())
nextSelectedThread = requestBuffers.begin();
}
std::map<Thread, std::deque<gp*>>::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<Thread, std::deque<gp*>>::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<Thread, std::deque<gp*>>::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<Thread, std::deque<gp*>> &requestBuffer,
std::deque<gp*>::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<Thread, std::deque<gp*>>&)requestBuffer, requestBuffer.second.begin());
}
else
{
formed = batchFormation(memClk, (std::pair<Thread, std::deque<gp*>>&)requestBuffer, readyBatchesIter[requestBuffer.first].back() + 1);
}
} while (formed);
}
}

View File

@@ -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<Thread, std::deque<gp*>> requestBuffers;
std::map<Bank, std::deque<gp*>> bankBuffers;
std::map<Thread, std::deque<gp*>> readybatches;
std::map<Thread, std::deque<std::deque<gp*>::iterator>> readyBatchesIter;
std::map<Thread, unsigned int> inFlightMemRequestCounter;
std::map<Thread, unsigned int> 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<Thread, std::deque<gp*>> &requestBuffer, std::deque<gp*>::iterator beginIter);
void multiBatchFormation(sc_time memClk);
bool pickSJF();
bool pickRR();
void drain(sc_time memClk, std::deque<gp*>::iterator last);
bool existLowIntensityThread();
bool isSystemLightlyLoaded();