📄 resourcemanager.h
字号:
/// ReleaseOnlyBorrowedCores - scheduler should release all its borrowed cores.
/// </param>
/// <param name="borrowedCoresReleased">
/// Tells whether a previous call to this API was made for the scheduler that successfully released borrowed cores. If this is true
/// the scheduler should only have owned cores.
/// </param>
bool ReleaseSchedulerResources(SchedulerProxy *pSchedulerProxy, unsigned int numberToFree, bool borrowedCoresReleased = false);
/// <summary>
/// Called to claim back any previously released cores that were not allocated to a different scheduler. If released
/// cores were allocated (stolen), the proxy needs to notify its scheduler to give up the related virtual processor
/// roots.
/// <summary>
void RestoreSchedulerResources(SchedulerProxy * pSchedulerProxy);
/// <summary>
/// Called to allocate a single resource from the current scheduler proxy to accomodate an external thread during
/// thread subscription. This function is called only if there are cores above minimum that this proxy can replace
/// with the external thread.
/// <summary>
unsigned int ReleaseSchedulerResourceAboveMin(SchedulerProxy * pSchedulerProxy);
/// <summary>
/// Starts up the dynamic RM worker thread if it is on standby, or creates a thread if one is not already created.
/// The worker thread wakes up at fixed intervals and load balances resources among schedulers, until it it put on standby.
/// </summary>
void CreateDynamicRMWorker();
/// <summary>
/// Routine that performs dynamic resource management among existing schedulers at fixed time intervals.
/// </summary>
void DynamicResourceManager();
/// <summary>
/// Performs a dynamic resource allocation based on feedback from hill climbing.
/// </summary>
void DoCoreMigration();
/// <summary>
/// When the number of schedulers in the RM goes from 2 to 1, this routine is invoked to make sure the remaining scheduler
/// has its desired number of cores, before putting the dynamic RM worker on standby. It is also called when there is just
/// one scheduler with external subscribed threads that it removes -> there is a chance that this move may allow us to allocate
/// more vprocs.
/// </summary>
bool DistributeCoresToSurvivingScheduler();
/// <summary>
/// This API is called by the dynamic RM worker thread when it starts up, and right after its state changed to
/// LoadBalance after being on Standby for a while. We need to find the existing schedulers, and discard the
/// statistics they have collected so far if any. Either we've never collected statistics for this scheduler before,
/// or too much/too little time has passed since we last collected statistics, and this information cannot be trusted.
/// </summary>
void DiscardExistingSchedulerStatistics();
/// <summary>
/// Ensures that the memory buffers needed for static and dynamic RM are of the right size, and initializes them.
/// </summary>
void InitializeRMBuffers();
/// <summary>
/// Populates data needed for allocation (static or dynamic).
/// </summary>
void PopulateCommonAllocationData(unsigned int index, SchedulerProxy * pSchedulerProxy, AllocationData * pAllocationData);
/// <summary>
/// Captures data needed for static allocation, for all existing schedulers. This includes determining which
/// cores on a scheduler are idle.
/// A number of preprocessing steps are are also preformed before we are ready to allocate cores for a new scheduler.
///
/// - If a borrowed core is now in use by the other scheduler(s) that own that core, it is taken away.
/// - If the scheduler with the borrowed core is now the only scheduler using the core, it is not considered borrowed any more.
/// </summary>
void SetupStaticAllocationData(SchedulerProxy * pNewProxy, bool fNeedsExternalThreadAllocation);
/// <summary>
/// Captures data needed for dynamic allocation for all existing schedulers. This includes gathering statistics
/// and invoking a per scheduler hill climbing instance, to get a suggested future allocation. Also, determines how may
/// idle cores a scheduler has.
/// </summary>
void PopulateDynamicAllocationData();
/// <summary>
/// Resets state that was set on the global cores during static or dynamic allocation.
/// </summary>
void ResetGlobalState();
/// <summary>
/// Toggles the idle state on a core and updates tracking counts.
/// </summary>
void ToggleRMIdleState(SchedulerNode * pAllocatedNode, SchedulerCore * pAllocatedCore,
GlobalNode * pGlobalNode, GlobalCore * pGlobalCore, AllocationData * pDRMData);
/// <summary>
/// A number of preprocessing steps are preformed before we are ready to migrate cores. They include handling of borrowed, idle,
/// and shared cores, as follows:
///
/// - If a borrowed core is now in use by the other scheduler(s) that own that core, it is taken away.
/// - If the scheduler with the borrowed core is now the only scheduler using the core, it is not considered borrowed anymore.
/// - If hill climbing has suggested an allocation increase for a scheduler that has idle cores, or an allocation decrease that
/// does not take away all its idle cores, the RM overrides it, setting the suggested allocation for that scheduler to
/// max(minCores, allocatedCores - idleCores).
///
/// The new value of suggested allocation is used for the following:
/// - If the suggested allocation is less than the current allocation for a scheduler that has shared cores (cores oversubscribed
/// with a different scheduler), those cores are taken away here, since we want to minimize sharing.
/// </summary>
void PreProcessDynamicAllocationData();
/// <summary>
/// Preprocessing steps for borrowed cores - both static and dynamic allocation start out with a call to this API.
/// </summary>
void HandleBorrowedCores(SchedulerProxy * pSchedulerProxy, AllocationData * pAllocationData);
/// <summary>
/// Preprocessing steps for shared cores - this is used during dynamic core migration.
/// </summary>
void HandleSharedCores(SchedulerProxy * pSchedulerProxy, DynamicAllocationData * pAllocationData);
/// <summary>
/// This routine increases the suggested allocation to desired, for schedulers with the following characteristics:
/// 1) Hill climbing has *not* recommended an allocation decrease.
/// 2) They are using all the cores allocated to them (no idle cores).
/// In the second round of core migration, we try to satisfy these schedulers' desired allocation.
/// </summary>
void IncreaseFullyLoadedSchedulerAllocations();
/// <summary>
/// Decides on the number of additional cores to give a set of schedulers, given what the schedulers need and what is available.
/// </summary>
unsigned int AdjustDynamicAllocation(unsigned int coresAvailable, unsigned int coresNeeded, unsigned int numReceivers);
/// <summary>
/// Initializes receiving proxy data in preparation for core transfer. Calcuates the number of partially filled nodes
/// for schedulers that are receiving cores, and sorts the receiving proxy data in increasing order of partial nodes.
/// </summary>
/// <returns>
/// Number of recivers that still need cores (allocation field of the receiving proxy data > 0).
/// </returns>
unsigned int PrepareReceiversForCoreTransfer(unsigned int numReceivers);
/// <summary>
/// Assigns one core at a time to a partially filled node on a receiving scheduler proxy, if possible
/// </summary>
bool FindCoreForPartiallyFilledNode(unsigned int& unusedCoreQuota,
unsigned int& usedCoreQuota,
DynamicAllocationData * pReceivingProxyData,
unsigned int numGivers);
/// <summary>
/// Attempts to assign cores to a receiver on a single empty node, taking cores from multiple givers if necessary.
/// </summary>
unsigned int FindBestFitExclusiveAllocation(unsigned int& unusedCoreQuota,
unsigned int& usedCoreQuota,
DynamicAllocationData * pReceivingProxyData,
unsigned int remainingReceivers,
unsigned int numGivers);
/// <summary>
/// Distributes unused cores and cores from scheduler proxies that are willing to give up cores to scheduler proxies that
/// need cores.
/// </summary>
void DistributeExclusiveCores(unsigned int totalCoresNeeded,
unsigned int unusedCoreQuota,
unsigned int usedCoreQuota,
unsigned int numReceivers,
unsigned int numGivers);
/// <summary>
/// Attempts to assign cores to a receiver on a single empty node, using idle cores.
/// </summary>
unsigned int FindBestFitIdleAllocation(unsigned int idleCoresAvailable, DynamicAllocationData * pReceivingProxyData, unsigned int remainingReceivers);
/// <summary>
/// Distributes idle cores to scheduler proxies that need cores.
/// </summary>
void DistributeIdleCores(unsigned int totalCoresAvailable, unsigned int numReceivers);
/// <summary>
/// Assigns a fixed number of unused or idle cores to a scheduler from a given node.
/// </summary>
void DynamicAssignCores(SchedulerProxy * pReceivingProxy, unsigned int nodeIndex, unsigned int numCoresToMigrate, bool fIdle);
/// <summary>
/// Transfers a fixed number of cores from one scheduler to another.
/// </summary>
void DynamicMigrateCores(DynamicAllocationData * pGivingProxyData, SchedulerProxy * pReceivingProxy, unsigned int nodeIndex, unsigned int numCoresToMigrate);
#if defined (CONCRT_TRACING)
/// <summary>
/// Captures the initial state of the global map at the beginning of core migration, each cycle.
/// </summary>
void TraceInitialDRMState();
/// <summary>
/// Captures data relating to an action during DRM preprocessing.
/// </summary>
void TracePreProcessingAction(SchedulerProxy * pProxy, unsigned int nodeIndex, unsigned int coreIndex,
bool fMarkedAsOwned, bool fBorrowedCoreRemoved, bool fSharedCoreRemoved, bool fIdleCore);
/// <summary>
/// Captures data relating to an action during DRM core migration.
/// </summary>
void TraceCoreMigrationAction(SchedulerProxy * pGiver, SchedulerProxy * pReceiver, unsigned int round, unsigned int nodeIndex,
unsigned int coreIndex, bool fUnusedCoreMigration, bool fIdleCoreSharing, bool fBorrowedByGiver,
bool fIdleOnGiver);
/// <summary>
/// Dumps allocations, for existing scheduler proxies, and a newly allocated scheduler proxy, if specified.
/// </summary>
void DumpAllocations(SchedulerProxy *pSchedulerProxy = NULL);
/// <summary>
/// Dumps the state of the global nodes in the RM - system wide view of resource allocation.
/// </summary>
void DumpGlobalNodes();
#endif
/// <summary>
/// Performs borrowed core validation. A core can be borrowed by only one scheduler at a time.
/// </summary>
void ValidateBorrowedCores();
/// <summary>
/// Performs state validations during dynamic core migration.
/// </summary>
void ValidateDRMSchedulerState();
/// <summary>
/// Main thread procedure for the dynamic RM worker thread.
/// </summary>
/// <param name="lpParameter">
/// Resource manager pointer passed to the worker thread.
/// </param>
/// <returns>
/// Status on thread exit.
/// </returns>
static DWORD CALLBACK DynamicRMThreadProc(LPVOID lpParameter);
/// <summary>
/// Given a set of scaled floating point allocations that add up to nSum, rounds them to integers.
/// </summary>
static void RoundUpScaledAllocations(AllocationData ** ppData, unsigned int count, unsigned int nSum);
};
} // namespace details
} // namespace Concurrency
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -