OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExecutorResourcePool.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <array>
20 #include <map>
21 #include <shared_mutex>
22 
24 #include "ResourceGrantPolicy.h"
25 #include "ResourceRequest.h"
26 
27 namespace ExecutorResourceMgr_Namespace {
28 
37  const ResourceSubtype resource_subtype) {
38  switch (resource_subtype) {
55  default:
56  UNREACHABLE();
58  }
59 }
60 
69 inline std::vector<ResourceSubtype> map_resource_type_to_resource_subtypes(
70  const ResourceType resource_type) {
71  switch (resource_type) {
86  default:
87  UNREACHABLE();
89  }
90 }
91 
99  size_t total_cpu_slots{0};
100  size_t total_gpu_slots{0};
104 
110 
113 
116 
117  size_t total_requests{0};
124 
126 
128  const size_t total_gpu_slots,
129  const size_t total_cpu_result_mem,
130  const size_t total_cpu_buffer_pool_mem,
131  const size_t total_gpu_buffer_pool_mem,
132  const size_t allocated_cpu_slots,
133  const size_t allocated_gpu_slots,
134  const size_t allocated_cpu_result_mem,
135  const size_t allocated_cpu_buffer_pool_mem,
136  const size_t allocated_gpu_buffer_pool_mem,
137  const size_t allocated_cpu_buffers,
138  const size_t allocated_gpu_buffers,
141  const size_t total_requests,
142  const size_t outstanding_requests,
143  const size_t outstanding_cpu_slots_requests,
144  const size_t outstanding_gpu_slots_requests,
148  : total_cpu_slots(total_cpu_slots)
149  , total_gpu_slots(total_gpu_slots)
150  , total_cpu_result_mem(total_cpu_result_mem)
151  , total_cpu_buffer_pool_mem(total_cpu_buffer_pool_mem)
152  , total_gpu_buffer_pool_mem(total_gpu_buffer_pool_mem)
153  , allocated_cpu_slots(allocated_cpu_slots)
154  , allocated_gpu_slots(allocated_gpu_slots)
155  , allocated_cpu_result_mem(allocated_cpu_result_mem)
156  , allocated_cpu_buffer_pool_mem(allocated_cpu_buffer_pool_mem)
157  , allocated_gpu_buffer_pool_mem(allocated_gpu_buffer_pool_mem)
158  , allocated_cpu_buffers(allocated_cpu_buffers)
159  , allocated_gpu_buffers(allocated_gpu_buffers)
160  , allocated_temp_cpu_buffer_pool_mem(allocated_temp_cpu_buffer_pool_mem)
161  , allocated_temp_gpu_buffer_pool_mem(allocated_temp_gpu_buffer_pool_mem)
162  , total_requests(total_requests)
163  , outstanding_requests(outstanding_requests)
164  , outstanding_cpu_slots_requests(outstanding_cpu_slots_requests)
165  , outstanding_gpu_slots_requests(outstanding_gpu_slots_requests)
166  , outstanding_cpu_result_mem_requests(outstanding_cpu_result_mem_requests)
167  , outstanding_cpu_buffer_pool_mem_requests(outstanding_cpu_buffer_pool_mem_requests)
168  , outstanding_gpu_buffer_pool_mem_requests(
169  outstanding_gpu_buffer_pool_mem_requests) {}
170 };
171 
177  size_t cpu_slots{0};
178  size_t gpu_slots{0};
179  size_t cpu_result_mem{0};
180 
181  // Below is only relevant if buffer_mem_gated_per_slot is true
185 
186  bool is_empty() const {
187  return cpu_slots == 0 && gpu_slots == 0 && cpu_result_mem == 0;
188  }
189 
190  void print() const;
191 
192  std::string to_string() const;
193 };
194 
195 using BufferPoolChunkMap =
196  std::map<ChunkKey, std::pair<size_t, size_t>>; // Value is reference count and size
197 
238  public:
240  const std::vector<std::pair<ResourceType, size_t>>& total_resources,
241  const std::vector<ConcurrentResourceGrantPolicy>&
242  concurrent_resource_grant_policies,
243  const std::vector<ResourceGrantPolicy>& max_per_request_resource_grant_policies);
244 
245  void log_parameters() const;
246 
247  std::vector<ResourceRequestGrant> calc_static_resource_grant_ranges_for_request(
248  const std::vector<ResourceRequest>& resource_requests) const;
249 
265  std::pair<ResourceGrant, ResourceGrant> calc_min_max_resource_grants_for_request(
266  const RequestInfo& resource_request) const;
267 
268  bool can_currently_satisfy_request(const ResourceGrant& min_resource_grant,
269  const ChunkRequestInfo& chunk_request_info) const;
270 
293  std::pair<bool, ResourceGrant> determine_dynamic_resource_grant(
294  const ResourceGrant& min_resource_grant,
295  const ResourceGrant& max_resource_grant,
296  const ChunkRequestInfo& chunk_request_info,
297  const double max_request_backoff_ratio) const;
298 
320  void allocate_resources(const ResourceGrant& resource_grant,
321  const ChunkRequestInfo& chunk_request_info);
322 
331  void deallocate_resources(const ResourceGrant& resource_grant,
332  const ChunkRequestInfo& chunk_request_info);
333 
342  std::pair<size_t, size_t> get_resource_info(const ResourceType resource_type) const;
343 
352 
367  void set_resource(const ResourceType resource_type, const size_t resource_quantity);
368 
370  const ResourceType resource_type) const {
371  return concurrent_resource_grant_policies_[static_cast<size_t>(resource_type)];
372  }
373 
375  const ResourceSubtype resource_subtype) const {
376  return max_resource_grants_per_request_policies_[static_cast<size_t>(
377  resource_subtype)];
378  }
379 
396  const ConcurrentResourceGrantPolicy& concurrent_resource_grant_policy);
397 
398  private:
399  void init(
400  const std::vector<std::pair<ResourceType, size_t>>& total_resources,
401  const std::vector<ConcurrentResourceGrantPolicy>&
402  concurrent_resource_grant_policies,
403  const std::vector<ResourceGrantPolicy>& max_per_request_resource_grant_policies);
404 
407 
408  void throw_insufficient_resource_error(const ResourceSubtype resource_subtype,
409  const size_t min_resource_requested) const;
410 
412  const size_t requested_resource_quantity,
413  const size_t min_requested_resource_quantity,
414  const size_t max_grantable_resource_quantity) const;
415 
416  std::pair<size_t, size_t> calc_min_dependent_resource_grant_for_request(
417  const size_t min_requested_dependent_resource_quantity,
418  const size_t min_requested_independent_resource_quantity,
419  const size_t dependent_to_independent_resource_ratio) const;
420 
421  std::pair<size_t, size_t> calc_max_dependent_resource_grant_for_request(
422  const size_t requested_dependent_resource_quantity,
423  const size_t min_requested_dependent_resource_quantity,
424  const size_t max_grantable_dependent_resource_quantity,
425  const size_t min_requested_independent_resource_quantity,
426  const size_t max_grantable_independent_resource_quantity,
427  const size_t dependent_to_independent_resource_ratio) const;
428 
430  const size_t resource_total,
431  const size_t resource_allocated,
432  const ConcurrentResourceGrantPolicy& concurrent_resource_grant_policy) const;
433 
435  const size_t resource_request,
436  const size_t resource_total,
437  const size_t resource_allocated,
438  const size_t global_outstanding_requests,
439  const ConcurrentResourceGrantPolicy& concurrent_resource_grant_policy) const;
440 
441  // Unlocked internal version
443  const ResourceGrant& min_resource_grant,
444  const ChunkRequestInfo& chunk_request_info) const;
445 
447  const ResourceGrant& min_resource_grant,
448  const ChunkRequestInfo& chunk_request_info) const;
450  const ChunkRequestInfo& chunk_request_info) const;
451  size_t get_chunk_bytes_not_in_pool(const ChunkRequestInfo& chunk_request_info) const;
452  void add_chunk_requests_to_allocated_pool(const ResourceGrant& resource_grant,
453  const ChunkRequestInfo& chunk_request_info);
455  const ResourceGrant& resource_grant,
456  const ChunkRequestInfo& chunk_request_info);
457 
459  const size_t min_resource_requested,
460  const size_t max_resource_requested,
461  const size_t resource_allocated,
462  const size_t total_resource,
463  const double max_request_backoff_ratio) const;
464 
466 
468  const ExecutorDeviceType memory_pool_type) const {
469  return memory_pool_type == ExecutorDeviceType::CPU
472  }
473 
474  inline bool is_resource_valid(const ResourceType resource_type) const {
475  return resource_type_validity_[static_cast<size_t>(resource_type)];
476  }
477 
478  inline size_t get_total_resource(const ResourceType resource_type) const {
479  return total_resources_[static_cast<size_t>(resource_type)];
480  }
481 
483  const ResourceSubtype resource_subtype) const {
484  return allocated_resources_[static_cast<size_t>(resource_subtype)];
485  }
486 
487  size_t get_allocated_resource_of_type(const ResourceType resource_type) const;
488 
490  const ResourceSubtype resource_subtype) const {
491  return max_resource_grants_per_request_[static_cast<size_t>(resource_subtype)];
492  }
493 
495  const ResourceType resource_type) const {
496  return total_per_resource_num_requests_[static_cast<size_t>(resource_type)];
497  }
498 
500  const ResourceType resource_type) {
501  return ++total_per_resource_num_requests_[static_cast<size_t>(resource_type)];
502  }
503 
505  const ResourceType resource_type) {
506  return --total_per_resource_num_requests_[static_cast<size_t>(resource_type)];
507  }
508 
510  const ResourceType resource_type) const {
511  return outstanding_per_resource_num_requests_[static_cast<size_t>(resource_type)];
512  }
513 
515  const ResourceType resource_type) {
516  return ++outstanding_per_resource_num_requests_[static_cast<size_t>(resource_type)];
517  }
518 
520  const ResourceType resource_type) {
521  return --outstanding_per_resource_num_requests_[static_cast<size_t>(resource_type)];
522  }
523 
524  std::array<size_t, ResourceTypeSize>
525  total_resources_{}; // Will be value initialized to 0s
526  std::array<bool, ResourceTypeSize> resource_type_validity_{
527  false}; // Will be value initialized to false
528  std::array<size_t, ResourceSubtypeSize>
529  allocated_resources_{}; // Will be value initialized to 0s
530  std::array<ResourceGrantPolicy, ResourceSubtypeSize>
532  std::array<size_t, ResourceSubtypeSize> max_resource_grants_per_request_{};
533  std::array<ConcurrentResourceGrantPolicy, ResourceTypeSize>
535 
538 
539  std::array<size_t, ResourceTypeSize>
540  total_per_resource_num_requests_{}; // Will be value initialized to 0s
541 
542  std::array<size_t, ResourceTypeSize>
543  outstanding_per_resource_num_requests_{}; // Will be value initialized to 0s
544 
547 
550 };
551 
552 } // namespace ExecutorResourceMgr_Namespace
size_t get_total_resource(const ResourceType resource_type) const
A container for various stats about the current state of the ExecutorResourcePool. Note that ExecutorResourcePool does not persist a struct of this type, but rather builds one on the fly when ExecutorResourcePool::get_resource_info() is called.
A container to store requested and minimum neccessary resource requests across all resource types cur...
size_t get_chunk_bytes_not_in_pool(const ChunkRequestInfo &chunk_request_info) const
ResourcePoolInfo get_resource_info() const
Returns a struct detailing the allocated and total available resources of each type tracked in Execut...
std::array< size_t, ResourceSubtypeSize > allocated_resources_
bool can_currently_satisfy_request(const ResourceGrant &min_resource_grant, const ChunkRequestInfo &chunk_request_info) const
std::array< bool, ResourceTypeSize > resource_type_validity_
size_t get_allocated_resource_of_subtype(const ResourceSubtype resource_subtype) const
std::array< size_t, ResourceTypeSize > total_resources_
ChunkRequestInfo get_requested_chunks_not_in_pool(const ChunkRequestInfo &chunk_request_info) const
void set_resource(const ResourceType resource_type, const size_t resource_quantity)
Sets the quantity of resource_type to resource_quantity. If pool has outstanding requests, will throw. Responsibility of allowing the pool to empty and preventing concurrent requests while this operation is running is left to the caller (in particular, ExecutorResourceMgr::set_resource pauses the process queue, which waits until all executing requests are finished before yielding to the caller, before calling this method).
const ResourceGrantPolicy & get_max_resource_grant_per_request_policy(const ResourceSubtype resource_subtype) const
void deallocate_resources(const ResourceGrant &resource_grant, const ChunkRequestInfo &chunk_request_info)
Deallocates resources granted to a requestor such that they can be used for other requests...
#define UNREACHABLE()
Definition: Logger.h:338
ResourceType
Stores the resource type for a ExecutorResourcePool request.
std::vector< ResourceSubtype > map_resource_type_to_resource_subtypes(const ResourceType resource_type)
Returns the 1-or-more ResourceSubtypes associated with a given ResourceType.
bool is_resource_valid(const ResourceType resource_type) const
bool can_currently_satisfy_request_impl(const ResourceGrant &min_resource_grant, const ChunkRequestInfo &chunk_request_info) const
size_t calc_max_resource_grant_for_request(const size_t requested_resource_quantity, const size_t min_requested_resource_quantity, const size_t max_grantable_resource_quantity) const
std::map< ChunkKey, std::pair< size_t, size_t >> BufferPoolChunkMap
Specifies the policies for resource grants in the presence of other requests, both under situations o...
void add_chunk_requests_to_allocated_pool(const ResourceGrant &resource_grant, const ChunkRequestInfo &chunk_request_info)
size_t determine_dynamic_single_resource_grant(const size_t min_resource_requested, const size_t max_resource_requested, const size_t resource_allocated, const size_t total_resource, const double max_request_backoff_ratio) const
std::array< size_t, ResourceTypeSize > total_per_resource_num_requests_
ExecutorDeviceType
ResourceSubtype
Stores the resource sub-type for a ExecutorResourcePool request.
bool can_currently_satisfy_chunk_request(const ResourceGrant &min_resource_grant, const ChunkRequestInfo &chunk_request_info) const
size_t get_total_allocated_buffer_pool_mem_for_level(const ExecutorDeviceType memory_pool_type) const
size_t increment_outstanding_per_resource_num_requests(const ResourceType resource_type)
std::pair< ResourceGrant, ResourceGrant > calc_min_max_resource_grants_for_request(const RequestInfo &resource_request) const
Given the provided resource_request, statically calculate the minimum and maximum grantable resources...
std::vector< ResourceRequestGrant > calc_static_resource_grant_ranges_for_request(const std::vector< ResourceRequest > &resource_requests) const
void allocate_resources(const ResourceGrant &resource_grant, const ChunkRequestInfo &chunk_request_info)
Given a resource grant (assumed to be computed in determine_dynamic_resource_grant), actually allocate (reserve) the resources in the pool so other requestors (queries) cannot use those resources until returned to the pool.
Specifies the resources of each type for a given resource grant.
void set_concurrent_resource_grant_policy(const ConcurrentResourceGrantPolicy &concurrent_resource_grant_policy)
Resets the concurrent resource grant policy object, which specifies a ResourceType as well as normal ...
ResourcePoolInfo(const size_t total_cpu_slots, const size_t total_gpu_slots, const size_t total_cpu_result_mem, const size_t total_cpu_buffer_pool_mem, const size_t total_gpu_buffer_pool_mem, const size_t allocated_cpu_slots, const size_t allocated_gpu_slots, const size_t allocated_cpu_result_mem, const size_t allocated_cpu_buffer_pool_mem, const size_t allocated_gpu_buffer_pool_mem, const size_t allocated_cpu_buffers, const size_t allocated_gpu_buffers, const size_t allocated_temp_cpu_buffer_pool_mem, const size_t allocated_temp_gpu_buffer_pool_mem, const size_t total_requests, const size_t outstanding_requests, const size_t outstanding_cpu_slots_requests, const size_t outstanding_gpu_slots_requests, const size_t outstanding_cpu_result_mem_requests, const size_t outstanding_cpu_buffer_pool_mem_requests, const size_t outstanding_gpu_buffer_pool_mem_requests)
size_t increment_total_per_resource_num_requests(const ResourceType resource_type)
std::pair< size_t, size_t > calc_max_dependent_resource_grant_for_request(const size_t requested_dependent_resource_quantity, const size_t min_requested_dependent_resource_quantity, const size_t max_grantable_dependent_resource_quantity, const size_t min_requested_independent_resource_quantity, const size_t max_grantable_independent_resource_quantity, const size_t dependent_to_independent_resource_ratio) const
bool check_request_against_global_policy(const size_t resource_total, const size_t resource_allocated, const ConcurrentResourceGrantPolicy &concurrent_resource_grant_policy) const
ExecutorResourcePool(const std::vector< std::pair< ResourceType, size_t >> &total_resources, const std::vector< ConcurrentResourceGrantPolicy > &concurrent_resource_grant_policies, const std::vector< ResourceGrantPolicy > &max_per_request_resource_grant_policies)
Specifies the policy for granting a resource of a specific ResourceSubtype. Note that this policy onl...
ExecutorResourcePool keeps track of available compute and memory resources and can be queried to get ...
size_t decrement_total_per_resource_num_requests(const ResourceType resource_type)
std::pair< bool, ResourceGrant > determine_dynamic_resource_grant(const ResourceGrant &min_resource_grant, const ResourceGrant &max_resource_grant, const ChunkRequestInfo &chunk_request_info, const double max_request_backoff_ratio) const
Determines the actual resource grant to give a query (which will be somewhere between the provided mi...
std::pair< size_t, size_t > calc_min_dependent_resource_grant_for_request(const size_t min_requested_dependent_resource_quantity, const size_t min_requested_independent_resource_quantity, const size_t dependent_to_independent_resource_ratio) const
std::array< ConcurrentResourceGrantPolicy, ResourceTypeSize > concurrent_resource_grant_policies_
ResourceType map_resource_subtype_to_resource_type(const ResourceSubtype resource_subtype)
Returns the ResourceType associated with a given ResourceSubtype
void remove_chunk_requests_from_allocated_pool(const ResourceGrant &resource_grant, const ChunkRequestInfo &chunk_request_info)
void init(const std::vector< std::pair< ResourceType, size_t >> &total_resources, const std::vector< ConcurrentResourceGrantPolicy > &concurrent_resource_grant_policies, const std::vector< ResourceGrantPolicy > &max_per_request_resource_grant_policies)
size_t get_outstanding_per_resource_num_requests(const ResourceType resource_type) const
std::array< size_t, ResourceTypeSize > outstanding_per_resource_num_requests_
size_t get_max_resource_grant_per_request(const ResourceSubtype resource_subtype) const
bool check_request_against_policy(const size_t resource_request, const size_t resource_total, const size_t resource_allocated, const size_t global_outstanding_requests, const ConcurrentResourceGrantPolicy &concurrent_resource_grant_policy) const
std::shared_timed_mutex shared_mutex
Specifies all DataMgr chunks needed for a query step/request, along with their sizes in bytes...
size_t get_total_per_resource_num_requests(const ResourceType resource_type) const
std::array< size_t, ResourceSubtypeSize > max_resource_grants_per_request_
size_t decrement_outstanding_per_resource_num_requests(const ResourceType resource_type)
void throw_insufficient_resource_error(const ResourceSubtype resource_subtype, const size_t min_resource_requested) const
size_t get_allocated_resource_of_type(const ResourceType resource_type) const
std::array< ResourceGrantPolicy, ResourceSubtypeSize > max_resource_grants_per_request_policies_
ConcurrentResourceGrantPolicy get_concurrent_resource_grant_policy(const ResourceType resource_type) const