First try to form multiple ready batches
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user