339 lines
7.9 KiB
C++
339 lines
7.9 KiB
C++
/*
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
All rights reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
|
|
compliance with the License. You may obtain a copy of the License
|
|
at http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
|
|
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
|
|
|
|
See the Apache Version 2.0 License for specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
#include "DrKernel.h"
|
|
|
|
template DRDECLARECLASS(DrStringDictionary<DrResourceRef>);
|
|
|
|
DrResource::DrResource(DrResourceLevel level, DrString name, DrString locality, DrResourcePtr parent)
|
|
{
|
|
m_level = level;
|
|
m_name = name;
|
|
m_locality = locality;
|
|
m_parent = parent;
|
|
m_children = DrNew DrResourceList();
|
|
|
|
if (m_parent != DrNull)
|
|
{
|
|
m_parent->GetChildren()->Add(this);
|
|
}
|
|
}
|
|
|
|
void DrResource::Discard()
|
|
{
|
|
m_parent = DrNull;
|
|
if (m_children != DrNull)
|
|
{
|
|
int i;
|
|
for (i=0; i<m_children->Size(); ++i)
|
|
{
|
|
m_children[i]->Discard();
|
|
}
|
|
}
|
|
m_children = DrNull;
|
|
}
|
|
|
|
DrResourceLevel DrResource::GetLevel()
|
|
{
|
|
return m_level;
|
|
}
|
|
|
|
DrString DrResource::GetName()
|
|
{
|
|
return m_name;
|
|
}
|
|
|
|
DrString DrResource::GetLocality()
|
|
{
|
|
return m_locality;
|
|
}
|
|
|
|
DrResourcePtr DrResource::GetParent()
|
|
{
|
|
return m_parent;
|
|
}
|
|
|
|
DrResourceListRef DrResource::GetChildren()
|
|
{
|
|
return m_children;
|
|
}
|
|
|
|
bool DrResource::Contains(DrResourcePtr resource)
|
|
{
|
|
if (resource->GetLevel() > m_level)
|
|
{
|
|
return false;
|
|
}
|
|
else if (resource->GetLevel() == m_level)
|
|
{
|
|
return (resource == this);
|
|
}
|
|
else
|
|
{
|
|
return Contains(resource->GetParent());
|
|
}
|
|
}
|
|
|
|
|
|
DrUniverse::DrUniverse()
|
|
{
|
|
m_resourceLock = DrNew DrCritSec();
|
|
|
|
m_resourceAtLevel = DrNew RAArray(DRL_Cluster+1);
|
|
int i;
|
|
for (i=DRL_Core; i<=DRL_Cluster; ++i)
|
|
{
|
|
m_resourceAtLevel[i] = DrNew DrResourceList();
|
|
}
|
|
m_resource = DrNew DrResourceDictionary();
|
|
}
|
|
|
|
void DrUniverse::Discard()
|
|
{
|
|
int i;
|
|
for (i=DRL_Core; i<=DRL_Cluster; ++i)
|
|
{
|
|
int j;
|
|
for (j=0; j<m_resourceAtLevel[i]->Size(); ++j)
|
|
{
|
|
m_resourceAtLevel[i][j]->Discard();
|
|
}
|
|
m_resourceAtLevel[i] = DrNull;
|
|
}
|
|
m_resourceAtLevel = DrNull;
|
|
m_resource = DrNull;
|
|
}
|
|
|
|
DrCritSecPtr DrUniverse::GetResourceLock()
|
|
{
|
|
return m_resourceLock;
|
|
}
|
|
|
|
void DrUniverse::AddResource(DrResourcePtr resource)
|
|
{
|
|
m_resourceAtLevel[resource->GetLevel()]->Add(resource);
|
|
m_resource->Add(resource->GetName().GetString(), resource);
|
|
}
|
|
|
|
DrResourceListRef DrUniverse::GetResources(DrResourceLevel level)
|
|
{
|
|
return m_resourceAtLevel[level];
|
|
}
|
|
|
|
DrResourcePtr DrUniverse::LookUpResource(DrNativeString name)
|
|
{
|
|
return LookUpResourceInternal(DrString(name));
|
|
}
|
|
|
|
DrResourcePtr DrUniverse::LookUpResourceInternal(DrString name)
|
|
{
|
|
DrResourceRef resource;
|
|
if (m_resource->TryGetValue(name.GetString(), resource))
|
|
{
|
|
return resource;
|
|
}
|
|
else
|
|
{
|
|
return DrNull;
|
|
}
|
|
}
|
|
|
|
|
|
DrAffinity::DrAffinity()
|
|
{
|
|
m_isHardConstraint = false;
|
|
m_weight = 0;
|
|
m_locality = DrNew DrResourceList();
|
|
}
|
|
|
|
void DrAffinity::SetHardConstraint(bool isHardConstraint)
|
|
{
|
|
m_isHardConstraint = isHardConstraint;
|
|
}
|
|
|
|
bool DrAffinity::GetHardConstraint()
|
|
{
|
|
return m_isHardConstraint;
|
|
}
|
|
|
|
void DrAffinity::SetWeight(UINT64 weight)
|
|
{
|
|
m_weight = weight;
|
|
}
|
|
|
|
UINT64 DrAffinity::GetWeight()
|
|
{
|
|
return m_weight;
|
|
}
|
|
|
|
void DrAffinity::AddLocality(DrResourcePtr locality)
|
|
{
|
|
m_locality->Add(locality);
|
|
}
|
|
|
|
DrResourceListRef DrAffinity::GetLocalityArray()
|
|
{
|
|
return m_locality;
|
|
}
|
|
|
|
DrAffinityRef DrAffinityIntersector::IntersectHardConstraints(DrAffinityPtr existingConstraints,
|
|
DrAffinityListRef newAffinities)
|
|
{
|
|
DrAffinityRef constraints = existingConstraints;
|
|
|
|
int i;
|
|
for (i=0; i<newAffinities->Size(); ++i)
|
|
{
|
|
DrAffinityPtr a = newAffinities[i];
|
|
if (a->GetHardConstraint())
|
|
{
|
|
if (constraints == DrNull)
|
|
{
|
|
constraints = DrNew DrAffinity();
|
|
constraints->SetHardConstraint(true);
|
|
|
|
int j;
|
|
for (j=0; j<a->GetLocalityArray()->Size(); ++j)
|
|
{
|
|
constraints->GetLocalityArray()->Add(a->GetLocalityArray()[j]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int j = 0;
|
|
while (j<constraints->GetLocalityArray()->Size())
|
|
{
|
|
DrResourcePtr c = constraints->GetLocalityArray()[j];
|
|
|
|
int k;
|
|
for (k=0; k<a->GetLocalityArray()->Size(); ++k)
|
|
{
|
|
DrResourcePtr r = a->GetLocalityArray()[k];
|
|
if (c->Contains(r) || r->Contains(c))
|
|
{
|
|
if (r->GetLevel() < c->GetLevel())
|
|
{
|
|
/* narrow the constraint */
|
|
constraints->GetLocalityArray()[j] = r;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (k == a->GetLocalityArray()->Size())
|
|
{
|
|
/* we can't keep this constraint */
|
|
constraints->GetLocalityArray()->RemoveAt(j);
|
|
}
|
|
else
|
|
{
|
|
++j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return constraints;
|
|
}
|
|
|
|
|
|
DrAffinityMerger::DrAffinityMerger()
|
|
{
|
|
m_dictionary = DrNew ResourceWeightDictionary();
|
|
}
|
|
|
|
void DrAffinityMerger::AccumulateWeights(DrAffinityListRef affinityList)
|
|
{
|
|
int i;
|
|
for (i=0; i<affinityList->Size(); ++i)
|
|
{
|
|
AccumulateWeights(affinityList[i]);
|
|
}
|
|
}
|
|
|
|
void DrAffinityMerger::AccumulateWeights(DrAffinityPtr affinity)
|
|
{
|
|
DrAssert(affinity->GetHardConstraint() == false);
|
|
|
|
DrResourceListRef list = affinity->GetLocalityArray();
|
|
int i;
|
|
for (i=0; i<list->Size(); ++i)
|
|
{
|
|
DrResourcePtr r = list[i];
|
|
do
|
|
{
|
|
UINT64 weight;
|
|
if (m_dictionary->TryGetValue(r, weight))
|
|
{
|
|
weight += affinity->GetWeight();
|
|
m_dictionary->Replace(r, weight);
|
|
}
|
|
else
|
|
{
|
|
m_dictionary->Add(r, affinity->GetWeight());
|
|
}
|
|
|
|
/* also accumulate the coarser-level information */
|
|
r = r->GetParent();
|
|
} while (r != DrNull);
|
|
}
|
|
}
|
|
|
|
DrAffinityListRef DrAffinityMerger::GetMergedAffinities(DrFloatArrayRef levelThreshold)
|
|
{
|
|
DrUINT64ArrayRef levelTotal = DrNew DrUINT64Array(DRL_Cluster + 1);
|
|
|
|
int level;
|
|
for (level = DRL_Core; level <= DRL_Cluster; ++level)
|
|
{
|
|
levelTotal[level] = 0;
|
|
}
|
|
|
|
ResourceWeightDictionary::DrEnumerator eSum = m_dictionary->GetDrEnumerator();
|
|
while (eSum.MoveNext())
|
|
{
|
|
levelTotal[eSum.GetKey()->GetLevel()] += eSum.GetValue();
|
|
}
|
|
|
|
for (level = DRL_Core; level <= DRL_Cluster; ++level)
|
|
{
|
|
levelTotal[level] = (UINT64) ((float) levelTotal[level] * levelThreshold[level]);
|
|
}
|
|
|
|
DrAffinityListRef l = DrNew DrAffinityList();
|
|
|
|
ResourceWeightDictionary::DrEnumerator eFilter = m_dictionary->GetDrEnumerator();
|
|
while (eFilter.MoveNext())
|
|
{
|
|
DrResourcePtr resource = eFilter.GetKey();
|
|
UINT64 weight = eFilter.GetValue();
|
|
level = resource->GetLevel();
|
|
if (weight >= levelTotal[level])
|
|
{
|
|
DrAffinityRef a = DrNew DrAffinity();
|
|
a->SetWeight(weight);
|
|
a->AddLocality(resource);
|
|
l->Add(a);
|
|
}
|
|
}
|
|
|
|
return l;
|
|
}
|