Initial commit

This commit is contained in:
Matthias
2017-04-11 15:49:21 +02:00
commit ec80b339e2
2081 changed files with 968992 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
#pragma once
#include <wfr/common/resource/Resource.h>
#include <wfr/common/types/WfrTypes.h>
#include <mutex>
#include <thread>
#include <memory>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <condition_variable>
namespace wfr {
// Forward declarations
namespace wep {
class WorkflowExecutionPlan;
class AtomicWepNode;
}
namespace enactment {
class EnactmentEngine;
}
namespace execution {
class ExecutionManager;
}
namespace prediction {
class PredictionManager;
}
namespace resource {
class ResourceManager;
}
// Main namespace
namespace scheduling {
// Forward declaration
class SchedulingDecision;
/*
* Represents the interface every scheduler needs to implement.
*
* Workflow execution sequence:
* 1) registerWEP() is called by enactment engine to register new workflow instance
* 2) notifyWEPUpdate() is called by enactment engine to notify scheduler of workflow progress
* 3) The scheduler creates scheduling decisions objects and passes them to the execution layer
* - uses convenience function SchedulerBase::executeSchedulingDecision, or
* - directly calls ExecutionManager::executeSchedulingDecision
* 4) The execution layer calls notifySchedulingDecisionStatusUpdate to notify scheduler about executed (or failed) activities.
* - the scheduler needs then to call EnactmentEngine::notifyActivityInstanceStateUpdate() to notify the enactment engine.
* - SchedulerBase already automatically notifies the enactment engine.
* 5) Goto 2) till unregisterWEP() is called.
*/
class AbstractScheduler {
public:
virtual ~AbstractScheduler() noexcept {}
/*
* Is called by the enactment engine to let the scheduler know of a new workflow instance.
*
* @param wep workflow execution plan object representing the workflow instance
* @param ee reference to enactment engine
*/
virtual void registerWEP(wep::WorkflowExecutionPlan& wep, enactment::EnactmentEngine& ee) noexcept = 0;
/*
* Is called by the enactment engine to let the scheduler know that a workflow instance has finished
*
* @param wep workflow execution plan object representing the workflow instance
*/
virtual void unregisterWEP(wep::WorkflowExecutionPlan& wep) noexcept = 0;
/*
* Is called by the enactment engine to let the scheduler know about changes to the workflow execution plan.
*
* @param wep workflow execution plan object representing the workflow instance
* @param readytoExecute set of new ready-to-execute activities (for convenience)
*/
virtual void notifyWEPUpdate(wep::WorkflowExecutionPlan& wep, std::set<wep::AtomicWepNode*> readyToExecute) noexcept = 0;
/*
* Called by the execution layer to notify the scheduler that an activity finished (or failed) execution.
*
* @param sd reference to scheduling decision object.
*/
virtual void notifySchedulingDecisionStatusUpdate(std::shared_ptr<SchedulingDecision> sd) noexcept = 0;
virtual double getCummulativePredictionTime() noexcept = 0;
};
/*
* Scheduler base class implementing common scheduler functionality.
*/
class SchedulerBase : public AbstractScheduler {
public:
struct WepMapEntry {
WepMapEntry(enactment::EnactmentEngine* engine, wep::WorkflowExecutionPlan* wep)
: engine(engine), wep(wep) {}
enactment::EnactmentEngine* engine;
wep::WorkflowExecutionPlan* wep;
std::set<std::shared_ptr<SchedulingDecision>> decisions;
void* userData = nullptr;
};
protected:
typedef std::map<wep::WorkflowExecutionPlan*, WepMapEntry> wepMap_t;
std::mutex schedulerMutex;
wepMap_t wepMap;
bool simulationMode;
double cummulativePredictionTime = 0;
protected:
// Hook functions for AbstractScheduler functions below to allow customisation of common functionality
virtual void _registerWEP(WepMapEntry& wepe, std::unique_lock<std::mutex>& schedulerLock) {};
virtual void _unregisterWEP(WepMapEntry& wepe, std::unique_lock<std::mutex>& schedulerLock) {}
virtual void _notifyWEPUpdate(WepMapEntry& wepe, std::set<wep::AtomicWepNode*> readyToExecute, std::unique_lock<std::mutex>& schedulerLock) {}
virtual void _notifySchedulingDecisionStatusUpdate(WepMapEntry& wepe, std::shared_ptr<SchedulingDecision> sd, std::unique_lock<std::mutex>& schedulerLock) {}
// Convenience functions for passing a scheduling decision to the execution layer.
bool executeSchedulingDecision(WepMapEntry& wepe, std::shared_ptr<SchedulingDecision> sd, std::unique_lock<std::mutex>& schedulerLock) noexcept;
public:
SchedulerBase();
virtual ~SchedulerBase() noexcept;
// From AbstractScheduler class
virtual void registerWEP(wep::WorkflowExecutionPlan& wep, enactment::EnactmentEngine& ee) noexcept override;
virtual void unregisterWEP(wep::WorkflowExecutionPlan& wep) noexcept override;
virtual void notifyWEPUpdate(wep::WorkflowExecutionPlan& wep, std::set<wep::AtomicWepNode*> readyToExecute) noexcept override;
virtual void notifySchedulingDecisionStatusUpdate(std::shared_ptr<SchedulingDecision> wep) noexcept override;
virtual double getCummulativePredictionTime() noexcept override { return cummulativePredictionTime; }
};
} /* namespace scheduling */
} /* namespace wfr */
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include <string>
#include <map>
#include <functional>
namespace wfr {
namespace scheduling {
class AbstractScheduler;
class SchedulerManager {
private:
static SchedulerManager* singleton;
private:
typedef std::map<std::string, std::function<AbstractScheduler*()>> factoryMap_t;
std::string defaultScheduler;
factoryMap_t schedulerFactories;
private:
SchedulerManager(std::string defaultScheduler);
public:
static void init(int argc, char** argv);
static void finish();
static SchedulerManager& getInstance();
public:
~SchedulerManager() {}
AbstractScheduler* getDefaultScheduler();
AbstractScheduler* getSchedulerByName(std::string& name);
void markSchedulerForDeletion(AbstractScheduler* scheduler);
};
} /* namespace scheduling */
} /* namespace wfr */
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include <wfr/scheduling/AbstractScheduler.h>
namespace wfr {
namespace wep {
class AtomicWepNode;
class WEPnode;
}
}
namespace wfr {
namespace scheduling {
class DummyScheduler: public wfr::scheduling::SchedulerBase {
private:
resource::ResourceManager& resourceManager;
prediction::PredictionManager& predictionManager;
public:
DummyScheduler(resource::ResourceManager& resourceManager, prediction::PredictionManager& predictionManager)
: resourceManager(resourceManager), predictionManager(predictionManager) {}
virtual void _notifyWEPUpdate(SchedulerBase::WepMapEntry& wepe, std::set<wep::AtomicWepNode*> readyToExecute, std::unique_lock<std::mutex>& schedulerLock);
};
} /* namespace scheduling */
} /* namespace wfr */
+104
View File
@@ -0,0 +1,104 @@
#pragma once
#include <wfr/scheduling/AbstractScheduler.h>
#include <wfr/prediction/PredictionManager.h>
#include <wfr/common/resource/Resource.h>
#include <wfr/common/resource/ResourceManager.h>
#include <wfr/common/types/WfrTypes.h>
#include <mutex>
#include <thread>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <iostream>
#include <condition_variable>
namespace wfr {
namespace wfs {
class AtomicActivityInstance;
}
namespace wep {
class AtomicWepNode;
class AbstractWepNode;
}
namespace resource {
class ResourceManager;
}
namespace prediction {
class PredictionManager;
}
}
namespace wfr {
namespace scheduling {
class HEFTScheduler: public scheduling::SchedulerBase {
protected:
struct InstanceUserData {
bool isComplete = false;
bool isScheduled = false;
NumericalMeasurement rank;
NumericalMeasurement averageComputingCost;
// resourceName => (fastest implementation, prediction);
std::map<resource::ComputingResourceType*, std::tuple<wfs::AtomicActivityImplementation*, prediction::ExecutionTimeResult>> predictions;
};
struct SchedulingQueueEntry {
InstanceUserData* instanceData = nullptr;
wfs::AtomicActivityInstance* instance = nullptr;
wep::AbstractWepNode* node = nullptr;
};
struct _SchedulingQueueEntryComparison {
bool operator()(const SchedulingQueueEntry& e1, const SchedulingQueueEntry& e2) {
if (e1.instanceData && !e2.instanceData) {
return false;
} else if (!e1.instanceData && e2.instanceData) {
return true;
} else if (e1.instanceData && e2.instanceData) {
return e1.instanceData->rank.getValue() < e2.instanceData->rank.getValue();
} else {
return false;
}
}
};
std::priority_queue<SchedulingQueueEntry, std::vector<SchedulingQueueEntry>, _SchedulingQueueEntryComparison> schedulingPriorityQueue;
resource::ResourceManager& resourceManager;
prediction::PredictionManager& predictionManager;
std::vector<std::string> debugLines;
wfr_size_t debugIteration = 0;
NumericalMeasurement getRank(wfs::AtomicActivityInstance& ai, InstanceUserData* instanceData, const std::vector<resource::ComputingResourceType*>& resourceTypes, const std::vector<resource::ComputingResource*>& resources);
NumericalMeasurement getAverageExecutionCost(wfs::AtomicActivityInstance& ai, InstanceUserData* instanceData, const std::vector<resource::ComputingResourceType*>& resources);
NumericalMeasurement getMaxSuccValue(wfs::AtomicActivityInstance& ai, InstanceUserData* instanceData, const std::vector<resource::ComputingResourceType*>& resourceTypes, const std::vector<resource::ComputingResource*>& resources);
public:
HEFTScheduler(resource::ResourceManager& resourceManager, prediction::PredictionManager& predictionManager)
: resourceManager(resourceManager), predictionManager(predictionManager) {}
~HEFTScheduler() {
/*for (auto s : debugLines) {
std::cout << s << std::endl;
}*/
}
virtual void _notifyWEPUpdate(SchedulerBase::WepMapEntry& wepe, std::set<wep::AtomicWepNode*> readyToExecute, std::unique_lock<std::mutex>& schedulerLock);
};
} /* namespace scheduling */
} /* namespace wfr */
@@ -0,0 +1,34 @@
#pragma once
#include <wfr/scheduling/AbstractScheduler.h>
namespace wfr {
namespace wep {
class AtomicWepNode;
class WEPnode;
}
}
namespace wfr {
namespace scheduling {
class JustInTimeScheduler: public wfr::scheduling::SchedulerBase {
private:
resource::ResourceManager& resourceManager;
prediction::PredictionManager& predictionManager;
std::set<wep::AtomicWepNode*> nodeQueue;
public:
JustInTimeScheduler(resource::ResourceManager& resourceManager, prediction::PredictionManager& predictionManager)
: resourceManager(resourceManager), predictionManager(predictionManager) {}
virtual void _notifyWEPUpdate(SchedulerBase::WepMapEntry& wepe, std::set<wep::AtomicWepNode*> readyToExecute, std::unique_lock<std::mutex>& schedulerLock);
};
} /* namespace scheduling */
} /* namespace wfr */
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <wfr/scheduling/AbstractScheduler.h>
namespace wfr {
namespace wep {
class AtomicWepNode;
class WEPnode;
}
}
namespace wfr {
namespace scheduling {
class RandomScheduler: public wfr::scheduling::SchedulerBase {
private:
resource::ResourceManager& resourceManager;
prediction::PredictionManager& predictionManager;
std::set<wep::AtomicWepNode*> nodeQueue;
public:
RandomScheduler(resource::ResourceManager& resourceManager, prediction::PredictionManager& predictionManager)
: resourceManager(resourceManager), predictionManager(predictionManager) {}
virtual void _notifyWEPUpdate(SchedulerBase::WepMapEntry& wepe, std::set<wep::AtomicWepNode*> readyToExecute, std::unique_lock<std::mutex>& schedulerLock);
};
} /* namespace scheduling */
} /* namespace wfr */