forked from OSchip/llvm-project
[MCA] Store extra information about processor resources in the ResourceManager.
Method ResourceManager::use() is responsible for updating the internal state of used processor resources, as well as notifying resource groups that contain used resources. Before this patch, method 'use()' didn't know how to quickly obtain the set of groups that contain a particular resource unit. It had to discover groups by perform a potentially slow search (done by iterating over the set of processor resource descriptors). With this patch, the relationship between resource units and groups is stored in the ResourceManager. That means, method 'use()' no longer has to search for groups. This gives an average speedup of ~4-5% on a release build. This patch also adds extra code comments in ResourceManager.h to better describe the resource mask layout, and how resouce indices are computed from resource masks. llvm-svn: 350387
This commit is contained in:
parent
4cebc9db04
commit
7bec693433
|
@ -139,7 +139,30 @@ class ResourceState {
|
|||
/// An index to the MCProcResourceDesc entry in the processor model.
|
||||
const unsigned ProcResourceDescIndex;
|
||||
/// A resource mask. This is generated by the tool with the help of
|
||||
/// function `mca::createProcResourceMasks' (see Support.h).
|
||||
/// function `mca::computeProcResourceMasks' (see Support.h).
|
||||
///
|
||||
/// Field ResourceMask only has one bit set if this resource state describes a
|
||||
/// processor resource unit (i.e. this is not a group). That means, we can
|
||||
/// quickly check if a resource is a group by simply counting the number of
|
||||
/// bits that are set in the mask.
|
||||
///
|
||||
/// The most significant bit of a mask (MSB) uniquely identifies a resource.
|
||||
/// Remaining bits are used to describe the composition of a group (Group).
|
||||
///
|
||||
/// Example (little endian):
|
||||
/// Resource | Mask | MSB | Group
|
||||
/// ---------+------------+------------+------------
|
||||
/// A | 0b000001 | 0b000001 | 0b000000
|
||||
/// | | |
|
||||
/// B | 0b000010 | 0b000010 | 0b000000
|
||||
/// | | |
|
||||
/// C | 0b010000 | 0b010000 | 0b000000
|
||||
/// | | |
|
||||
/// D | 0b110010 | 0b100000 | 0b010010
|
||||
///
|
||||
/// In this example, resources A, B and C are processor resource units.
|
||||
/// Only resource D is a group resource, and it contains resources B and C.
|
||||
/// That is because MSB(B) and MSB(C) are both contained within Group(D).
|
||||
const uint64_t ResourceMask;
|
||||
|
||||
/// A ProcResource can have multiple units.
|
||||
|
@ -279,10 +302,39 @@ typedef std::pair<unsigned, unsigned> BufferUsageEntry;
|
|||
/// In future, it can be extended to support itineraries too through the same
|
||||
/// public interface.
|
||||
class ResourceManager {
|
||||
// The resource manager owns all the ResourceState.
|
||||
// Set of resources available on the subtarget.
|
||||
//
|
||||
// There is an instance of ResourceState for every resource declared by the
|
||||
// target scheduling model.
|
||||
//
|
||||
// Elements of this vector are ordered by resource kind. In particular,
|
||||
// resource units take precedence over resource groups.
|
||||
//
|
||||
// The index of a processor resource in this vector depends on the value of
|
||||
// its mask (see the description of field ResourceState::ResourceMask). In
|
||||
// particular, it is computed as the position of the most significant bit set
|
||||
// (MSB) in the mask plus one (since we want to ignore the invalid resource
|
||||
// descriptor at index zero).
|
||||
//
|
||||
// Example (little endian):
|
||||
//
|
||||
// Resource | Mask | MSB | Index
|
||||
// ---------+---------+---------+-------
|
||||
// A | 0b00001 | 0b00001 | 1
|
||||
// | | |
|
||||
// B | 0b00100 | 0b00100 | 3
|
||||
// | | |
|
||||
// C | 0b10010 | 0b10000 | 5
|
||||
//
|
||||
//
|
||||
// The same index is also used to address elements within vector `Strategies`
|
||||
// and vector `Resource2Groups`.
|
||||
std::vector<std::unique_ptr<ResourceState>> Resources;
|
||||
std::vector<std::unique_ptr<ResourceStrategy>> Strategies;
|
||||
|
||||
// Used to quickly identify groups that own a particular resource unit.
|
||||
std::vector<uint64_t> Resource2Groups;
|
||||
|
||||
// Keeps track of which resources are busy, and how many cycles are left
|
||||
// before those become usable again.
|
||||
SmallDenseMap<ResourceRef, unsigned> BusyResources;
|
||||
|
|
|
@ -115,10 +115,11 @@ getStrategyFor(const ResourceState &RS) {
|
|||
return std::unique_ptr<ResourceStrategy>(nullptr);
|
||||
}
|
||||
|
||||
ResourceManager::ResourceManager(const MCSchedModel &SM) {
|
||||
ResourceManager::ResourceManager(const MCSchedModel &SM)
|
||||
: Resources(SM.getNumProcResourceKinds()),
|
||||
Strategies(SM.getNumProcResourceKinds()),
|
||||
Resource2Groups(SM.getNumProcResourceKinds(), 0) {
|
||||
computeProcResourceMasks(SM, ProcResID2Mask);
|
||||
Resources.resize(SM.getNumProcResourceKinds());
|
||||
Strategies.resize(SM.getNumProcResourceKinds());
|
||||
|
||||
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
|
||||
uint64_t Mask = ProcResID2Mask[I];
|
||||
|
@ -127,6 +128,24 @@ ResourceManager::ResourceManager(const MCSchedModel &SM) {
|
|||
llvm::make_unique<ResourceState>(*SM.getProcResource(I), I, Mask);
|
||||
Strategies[Index] = getStrategyFor(*Resources[Index]);
|
||||
}
|
||||
|
||||
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
|
||||
uint64_t Mask = ProcResID2Mask[I];
|
||||
unsigned Index = getResourceStateIndex(Mask);
|
||||
const ResourceState &RS = *Resources[Index];
|
||||
if (!RS.isAResourceGroup())
|
||||
continue;
|
||||
|
||||
uint64_t GroupMaskIdx = 1ULL << (Index - 1);
|
||||
Mask -= GroupMaskIdx;
|
||||
while (Mask) {
|
||||
// Extract lowest set isolated bit.
|
||||
uint64_t Unit = Mask & (-Mask);
|
||||
unsigned IndexUnit = getResourceStateIndex(Unit);
|
||||
Resource2Groups[IndexUnit] |= GroupMaskIdx;
|
||||
Mask ^= Unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManager::setCustomStrategyImpl(std::unique_ptr<ResourceStrategy> S,
|
||||
|
@ -179,17 +198,16 @@ void ResourceManager::use(const ResourceRef &RR) {
|
|||
if (RS.isReady())
|
||||
return;
|
||||
|
||||
// Notify to other resources that RR.first is no longer available.
|
||||
for (std::unique_ptr<ResourceState> &Res : Resources) {
|
||||
ResourceState &Current = *Res;
|
||||
if (!Current.isAResourceGroup() || Current.getResourceMask() == RR.first)
|
||||
continue;
|
||||
|
||||
if (Current.containsResource(RR.first)) {
|
||||
unsigned Index = getResourceStateIndex(Current.getResourceMask());
|
||||
Current.markSubResourceAsUsed(RR.first);
|
||||
Strategies[Index]->used(RR.first);
|
||||
}
|
||||
// Notify groups that RR.first is no longer available.
|
||||
uint64_t Users = Resource2Groups[RSID];
|
||||
while (Users) {
|
||||
// Extract lowest set isolated bit.
|
||||
unsigned GroupIndex = getResourceStateIndex(Users & (-Users));
|
||||
ResourceState &CurrentUser = *Resources[GroupIndex];
|
||||
CurrentUser.markSubResourceAsUsed(RR.first);
|
||||
Strategies[GroupIndex]->used(RR.first);
|
||||
// Reset lowest set bit.
|
||||
Users &= Users - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue