#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace wfr { namespace scheduling { std::pair SufferageScheduler::_getNextTaskToSchedule(std::map& estimatedTaskCompletionTimes) { wep::AtomicWepNode* selectedNode = nullptr; ECTEntry selectedEntry; bool firstIteration = true; for (auto n : estimatedTaskCompletionTimes) { if (firstIteration) { selectedNode = n.first; selectedEntry = n.second; firstIteration = false; } else { if (std::get<2>(n.second) > std::get<2>(selectedEntry)) { selectedNode = n.first; selectedEntry = n.second; } } } return std::make_pair(selectedNode, selectedEntry); } void SufferageScheduler::_notifyWEPUpdate(SchedulerBase::WepMapEntry& wepe, std::set readyToExecute, std::unique_lock& schedulerLock) { while (!readyToExecute.empty()) { std::map estimatedTaskCompletionTimes; auto resourceTypes = resourceManager.getComputingResourceTypes(); // Iterate over all tasks for (auto n : readyToExecute) { resource::ComputingResource* selectedResource = nullptr; double selectedEarliestEstimatedCompletionTime = -1; wfs::AtomicActivityImplementation* selectedImpl = nullptr; prediction::ExecutionTimeResult selectedPred; double selectedEarliestEstimatedCompletionTime2 = -1; std::map estimatedCompletionTimes; // Iterate over all resource types for (auto restype : resourceTypes) { // Get fastest implementation and predicted time for given resource type wfs::AtomicActivityImplementation* fastestImpl = nullptr; prediction::ExecutionTimeResult fastestPred; // Check cache first bool cacheHit = false; auto aaType = n->activity.baseActivity.baseTemplate.as().atomicActivityType.get(); auto& innerMap = implementationCache[aaType]; auto cacheEntry = innerMap.find(restype); if (cacheEntry != innerMap.end()) { fastestImpl = cacheEntry->second.first; fastestPred = cacheEntry->second.second; cacheHit = true; } if (!cacheHit) { // Cache miss auto& aat = n->activity.baseActivity.baseTemplate.as(); for (auto i : aat.atomicActivityType->getImplementations()) { auto execPred = predictionManager.predictExecutionTime(n->activity, *i, *restype); if (execPred.isValid() && (!fastestPred.isValid() || execPred < fastestPred)) { fastestPred = execPred; fastestImpl = i; } } // store into cache if (fastestPred.isValid()) { innerMap.insert({restype, {fastestImpl, fastestPred}}); } } if (fastestPred.isValid()) { // Iterate over all resources and calculate earliest completion time for (auto res : restype->getResources()) { auto ect = _getResourceEstimatedAvailableTime(res) + fastestPred.executionTime.getValue(); if (selectedEarliestEstimatedCompletionTime < 0 || ect < selectedEarliestEstimatedCompletionTime) { selectedEarliestEstimatedCompletionTime2 = selectedEarliestEstimatedCompletionTime; selectedEarliestEstimatedCompletionTime = ect; selectedResource = res; selectedImpl = fastestImpl; selectedPred = fastestPred; } else if (selectedEarliestEstimatedCompletionTime2 < 0 || ect < selectedEarliestEstimatedCompletionTime2) { selectedEarliestEstimatedCompletionTime2 = ect; } } // End: Iterate over all resources } } // End: Iterate over all resource types // Calculate sufferage double sufferage = 0; if (selectedEarliestEstimatedCompletionTime > 0 && selectedEarliestEstimatedCompletionTime2 > 0) { sufferage = selectedEarliestEstimatedCompletionTime2 - selectedEarliestEstimatedCompletionTime; } //std::cout << "selectedEarliestEstimatedCompletionTime " << n->activity.baseActivity.baseTemplate.activityName << ": " << selectedEarliestEstimatedCompletionTime << std::endl; //std::cout << "selectedEarliestEstimatedCompletionTime2 " << n->activity.baseActivity.baseTemplate.activityName << ": " << selectedEarliestEstimatedCompletionTime2 << std::endl; //std::cout << "Sufferage " << n->activity.baseActivity.baseTemplate.activityName << ": " << sufferage << std::endl; if (selectedResource) { estimatedTaskCompletionTimes.insert({n, std::make_tuple(selectedResource, selectedImpl, sufferage, selectedPred)}); } } // End: Iterate over all tasks // Select next task to schedule auto selectedTask = _getNextTaskToSchedule(estimatedTaskCompletionTimes); // Schedule task if (selectedTask.first) { auto reservation = resourceManager.reserveComputingResource(std::get<0>(selectedTask.second), 1, false); auto sd = std::make_shared(&selectedTask.first->activity, std::get<1>(selectedTask.second), wepe.wep, reservation); sd->setPrediction(std::get<3>(selectedTask.second)); selectedTask.first->activity.setInstanceStatus(wfs::ActivityInstanceStatus::Scheduled); executeSchedulingDecision(wepe, sd, schedulerLock); readyToExecute.erase(selectedTask.first); } } } void SufferageScheduler::_notifySchedulingDecisionStatusUpdate(WepMapEntry& wepe, std::shared_ptr sd, std::unique_lock& schedulerLock) {} } /* namespace scheduling */ } /* namespace wfr */