[GCS]GCS resource manager support scheduling resource (#12780)

* add part code

* add part code

* fix review comments

* rebase master

* add part code

* add part code

* fix review comments

* add part code

* fix code style

* fix ut bug

* fix ut bug

* fix review comments

* fix review comment

Co-authored-by: 灵洵 <fengbin.ffb@antgroup.com>
This commit is contained in:
fangfengbin
2020-12-15 10:27:55 +08:00
committed by GitHub
co-authored by 灵洵
parent 8cebe5cbe9
commit 43b9259d40
6 changed files with 89 additions and 34 deletions
+1 -1
View File
@@ -317,7 +317,7 @@ void GcsNodeManager::UpdateNodeRealtimeResources(
if (!light_report_resource_usage_enabled_ ||
gcs_resource_manager_->GetClusterResources().count(node_id) == 0 ||
resource_data.resources_available_changed()) {
gcs_resource_manager_->UpdateResources(
gcs_resource_manager_->SetAvailableResources(
node_id, ResourceSet(MapFromProtobuf(resource_data.resources_available())));
}
}
@@ -66,7 +66,7 @@ ScheduleMap GcsStrictPackStrategy::Schedule(
// Filter candidate nodes.
std::vector<std::pair<int64_t, NodeID>> candidate_nodes;
for (auto &node : context->cluster_resources_) {
if (required_resources.IsSubset(node.second)) {
if (required_resources.IsSubset(node.second.GetAvailableResources())) {
candidate_nodes.emplace_back((*context->node_to_bundles_)[node.first], node.first);
}
}
@@ -99,7 +99,8 @@ ScheduleMap GcsPackStrategy::Schedule(
for (const auto &bundle : bundles) {
const auto &required_resources = bundle->GetRequiredResources();
for (const auto &node : context->cluster_resources_) {
if (IsAvailableResourceSufficient(node.second, allocated_resources[node.first],
if (IsAvailableResourceSufficient(node.second.GetAvailableResources(),
allocated_resources[node.first],
required_resources)) {
schedule_map[bundle->BundleId()] = node.first;
allocated_resources[node.first].AddResources(required_resources);
@@ -135,7 +136,8 @@ ScheduleMap GcsSpreadStrategy::Schedule(
// that meets the resource requirements. `iter_begin` is the next node of the last
// selected node.
for (; iter != candidate_nodes.end(); ++iter) {
if (IsAvailableResourceSufficient(iter->second, allocated_resources[iter->first],
if (IsAvailableResourceSufficient(iter->second.GetAvailableResources(),
allocated_resources[iter->first],
required_resources)) {
schedule_map[bundle->BundleId()] = iter->first;
allocated_resources[iter->first].AddResources(required_resources);
@@ -153,8 +155,9 @@ ScheduleMap GcsSpreadStrategy::Schedule(
if (iter_begin != candidate_nodes.begin()) {
// Traverse all the nodes from `candidate_nodes.begin()` to `iter_begin`.
for (iter = candidate_nodes.begin(); iter != iter_begin; ++iter) {
if (IsAvailableResourceSufficient(
iter->second, allocated_resources[iter->first], required_resources)) {
if (IsAvailableResourceSufficient(iter->second.GetAvailableResources(),
allocated_resources[iter->first],
required_resources)) {
schedule_map[bundle->BundleId()] = iter->first;
allocated_resources[iter->first].AddResources(required_resources);
break;
@@ -207,7 +210,8 @@ ScheduleMap GcsStrictSpreadStrategy::Schedule(
auto iter = candidate_nodes.begin();
for (; iter != candidate_nodes.end(); ++iter) {
if (!allocated_resources.contains(iter->first) &&
IsAvailableResourceSufficient(iter->second, allocated_resources[iter->first],
IsAvailableResourceSufficient(iter->second.GetAvailableResources(),
allocated_resources[iter->first],
required_resources)) {
schedule_map[bundle->BundleId()] = iter->first;
allocated_resources[iter->first].AddResources(required_resources);
@@ -89,9 +89,10 @@ class GcsPlacementGroupSchedulerInterface {
/// ScheduleContext provides information that are needed for bundle scheduling decision.
class ScheduleContext {
public:
ScheduleContext(std::shared_ptr<absl::flat_hash_map<NodeID, int64_t>> node_to_bundles,
const absl::optional<std::shared_ptr<BundleLocations>> bundle_locations,
const absl::flat_hash_map<NodeID, ResourceSet> &cluster_resources)
ScheduleContext(
std::shared_ptr<absl::flat_hash_map<NodeID, int64_t>> node_to_bundles,
const absl::optional<std::shared_ptr<BundleLocations>> bundle_locations,
const absl::flat_hash_map<NodeID, SchedulingResources> &cluster_resources)
: node_to_bundles_(std::move(node_to_bundles)),
bundle_locations_(bundle_locations),
cluster_resources_(cluster_resources) {}
@@ -101,7 +102,7 @@ class ScheduleContext {
// The locations of existing bundles for this placement group.
const absl::optional<std::shared_ptr<BundleLocations>> bundle_locations_;
// The available resources of all nodes.
const absl::flat_hash_map<NodeID, ResourceSet> &cluster_resources_;
const absl::flat_hash_map<NodeID, SchedulingResources> &cluster_resources_;
};
class GcsScheduleStrategy {
+51 -16
View File
@@ -28,7 +28,7 @@ void GcsResourceManager::HandleGetResources(const rpc::GetResourcesRequest &requ
NodeID node_id = NodeID::FromBinary(request.node_id());
auto iter = cluster_resources_.find(node_id);
if (iter != cluster_resources_.end()) {
for (auto &resource : iter->second.items()) {
for (const auto &resource : iter->second.items()) {
(*reply->mutable_resources())[resource.first] = resource.second;
}
}
@@ -42,19 +42,27 @@ void GcsResourceManager::HandleUpdateResources(
NodeID node_id = NodeID::FromBinary(request.node_id());
RAY_LOG(DEBUG) << "Updating resources, node id = " << node_id;
auto iter = cluster_resources_.find(node_id);
auto to_be_updated_resources = request.resources();
std::unordered_map<std::string, double> to_be_updated_resources;
for (const auto &entry : request.resources()) {
to_be_updated_resources.emplace(entry.first, entry.second.resource_capacity());
}
if (iter != cluster_resources_.end()) {
for (auto &entry : to_be_updated_resources) {
for (const auto &entry : request.resources()) {
(*iter->second.mutable_items())[entry.first] = entry.second;
}
UpdateResourceCapacity(node_id, to_be_updated_resources);
auto on_done = [this, node_id, to_be_updated_resources, reply,
send_reply_callback](const Status &status) {
RAY_CHECK_OK(status);
rpc::NodeResourceChange node_resource_change;
node_resource_change.set_node_id(node_id.Binary());
for (auto &it : to_be_updated_resources) {
(*node_resource_change.mutable_updated_resources())[it.first] =
it.second.resource_capacity();
for (const auto &it : to_be_updated_resources) {
const auto &resource_name = it.first;
const auto &resource_capacity = it.second;
auto &node_updated_resources =
(*node_resource_change.mutable_updated_resources());
node_updated_resources[resource_name] = resource_capacity;
}
RAY_CHECK_OK(gcs_pub_sub_->Publish(NODE_RESOURCE_CHANNEL, node_id.Hex(),
node_resource_change.SerializeAsString(),
@@ -82,7 +90,9 @@ void GcsResourceManager::HandleDeleteResources(
auto resource_names = VectorFromProtobuf(request.resource_name_list());
auto iter = cluster_resources_.find(node_id);
if (iter != cluster_resources_.end()) {
for (auto &resource_name : resource_names) {
DeleteResources(node_id, resource_names);
for (const auto &resource_name : resource_names) {
RAY_IGNORE_EXPR(iter->second.mutable_items()->erase(resource_name));
}
auto on_done = [this, node_id, resource_names, reply,
@@ -115,7 +125,7 @@ void GcsResourceManager::HandleGetAllAvailableResources(
for (const auto &iter : cluster_scheduling_resources_) {
rpc::AvailableResources resource;
resource.set_node_id(iter.first.Binary());
for (const auto &res : iter.second.GetResourceAmountMap()) {
for (const auto &res : iter.second.GetAvailableResources().GetResourceAmountMap()) {
(*resource.mutable_resources_available())[res.first] = res.second.ToDouble();
}
reply->add_resources_list()->CopyFrom(resource);
@@ -134,14 +144,39 @@ void GcsResourceManager::Initialize(const GcsInitData &gcs_init_data) {
}
}
const absl::flat_hash_map<NodeID, ResourceSet> &GcsResourceManager::GetClusterResources()
const {
const absl::flat_hash_map<NodeID, SchedulingResources>
&GcsResourceManager::GetClusterResources() const {
return cluster_scheduling_resources_;
}
void GcsResourceManager::UpdateResources(const NodeID &node_id,
const ResourceSet &resources) {
cluster_scheduling_resources_[node_id] = resources;
void GcsResourceManager::SetAvailableResources(const NodeID &node_id,
const ResourceSet &resources) {
cluster_scheduling_resources_[node_id].SetAvailableResources(ResourceSet(resources));
}
void GcsResourceManager::UpdateResourceCapacity(
const NodeID &node_id,
const std::unordered_map<std::string, double> &changed_resources) {
auto iter = cluster_scheduling_resources_.find(node_id);
if (iter != cluster_scheduling_resources_.end()) {
SchedulingResources &scheduling_resources = iter->second;
for (const auto &entry : changed_resources) {
scheduling_resources.UpdateResourceCapacity(entry.first, entry.second);
}
} else {
cluster_scheduling_resources_.emplace(
node_id, SchedulingResources(ResourceSet(changed_resources)));
}
}
void GcsResourceManager::DeleteResources(
const NodeID &node_id, const std::vector<std::string> &deleted_resources) {
auto iter = cluster_scheduling_resources_.find(node_id);
if (iter != cluster_scheduling_resources_.end()) {
for (auto &resource_name : deleted_resources) {
iter->second.DeleteResource(resource_name);
}
}
}
void GcsResourceManager::OnNodeAdd(const NodeID &node_id) {
@@ -158,10 +193,10 @@ bool GcsResourceManager::AcquireResources(const NodeID &node_id,
const ResourceSet &required_resources) {
auto iter = cluster_scheduling_resources_.find(node_id);
if (iter != cluster_scheduling_resources_.end()) {
if (!required_resources.IsSubset(iter->second)) {
if (!required_resources.IsSubset(iter->second.GetAvailableResources())) {
return false;
}
iter->second.SubtractResourcesStrict(required_resources);
iter->second.Acquire(required_resources);
}
// If node dead, we will not find the node. This is a normal scenario, so it returns
// true.
@@ -172,7 +207,7 @@ bool GcsResourceManager::ReleaseResources(const NodeID &node_id,
const ResourceSet &acquired_resources) {
auto iter = cluster_scheduling_resources_.find(node_id);
if (iter != cluster_scheduling_resources_.end()) {
iter->second.AddResources(acquired_resources);
iter->second.Release(acquired_resources);
}
// If node dead, we will not find the node. This is a normal scenario, so it returns
// true.
+21 -6
View File
@@ -68,7 +68,7 @@ class GcsResourceManager : public rpc::NodeResourceInfoHandler {
/// Get the resources of all nodes in the cluster.
///
/// \return The resources of all nodes in the cluster.
const absl::flat_hash_map<NodeID, ResourceSet> &GetClusterResources() const;
const absl::flat_hash_map<NodeID, SchedulingResources> &GetClusterResources() const;
/// Handle a node registration.
///
@@ -80,11 +80,11 @@ class GcsResourceManager : public rpc::NodeResourceInfoHandler {
/// \param node_id The specified node id.
void OnNodeDead(const NodeID &node_id);
/// Update the resources of the specified node.
/// Set the available resources of the specified node.
///
/// \param node_id Id of a node.
/// \param resources Resources of a node.
void UpdateResources(const NodeID &node_id, const ResourceSet &resources);
/// \param resources Available resources of a node.
void SetAvailableResources(const NodeID &node_id, const ResourceSet &resources);
/// Acquire resources from the specified node. It will deduct directly from the node
/// resources.
@@ -110,15 +110,30 @@ class GcsResourceManager : public rpc::NodeResourceInfoHandler {
std::string DebugString() const;
/// Update the total resources and available resources of the specified node.
///
/// \param node_id Id of a node.
/// \param changed_resources Changed resources of a node.
void UpdateResourceCapacity(
const NodeID &node_id,
const std::unordered_map<std::string, double> &changed_resources);
private:
/// Delete the scheduling resources of the specified node.
///
/// \param node_id Id of a node.
/// \param deleted_resources Deleted resources of a node.
void DeleteResources(const NodeID &node_id,
const std::vector<std::string> &deleted_resources);
/// A publisher for publishing gcs messages.
std::shared_ptr<gcs::GcsPubSub> gcs_pub_sub_;
/// Storage for GCS tables.
std::shared_ptr<gcs::GcsTableStorage> gcs_table_storage_;
/// Cluster resources.
absl::flat_hash_map<NodeID, rpc::ResourceMap> cluster_resources_;
/// Map from node id to the resources of the node.
absl::flat_hash_map<NodeID, ResourceSet> cluster_scheduling_resources_;
/// Map from node id to the scheduling resources of the node.
absl::flat_hash_map<NodeID, SchedulingResources> cluster_scheduling_resources_;
/// Debug info.
enum CountType {
@@ -38,7 +38,7 @@ TEST_F(GcsResourceManagerTest, TestBasic) {
std::unordered_map<std::string, double> resource_map;
resource_map[cpu_resource] = 10;
ResourceSet resource_set(resource_map);
gcs_resource_manager_->UpdateResources(node_id, resource_set);
gcs_resource_manager_->UpdateResourceCapacity(node_id, resource_map);
// Get and check cluster resources.
const auto &cluster_resource = gcs_resource_manager_->GetClusterResources();