16 #ifndef TENSORFLOW_SERVING_CORE_SIMPLE_LOADER_H_
17 #define TENSORFLOW_SERVING_CORE_SIMPLE_LOADER_H_
22 #include "absl/types/optional.h"
23 #include "absl/types/variant.h"
24 #include "tensorflow/core/lib/core/errors.h"
25 #include "tensorflow/core/lib/core/status.h"
26 #include "tensorflow/core/platform/macros.h"
27 #include "tensorflow/core/platform/mem.h"
28 #include "tensorflow/core/platform/mutex.h"
29 #include "tensorflow/core/platform/types.h"
30 #include "tensorflow_serving/core/loader.h"
31 #include "tensorflow_serving/core/source_adapter.h"
32 #include "tensorflow_serving/resources/resource_util.h"
33 #include "tensorflow_serving/resources/resource_values.h"
34 #include "tensorflow_serving/util/any_ptr.h"
36 namespace tensorflow {
71 template <
typename ServableType>
75 using Creator = std::function<Status(std::unique_ptr<ServableType>*)>;
76 using CreatorWithMetadata =
77 std::function<Status(
const Metadata&, std::unique_ptr<ServableType>*)>;
78 using CreatorVariant = absl::variant<Creator, CreatorWithMetadata>;
81 using ResourceEstimator = std::function<Status(ResourceAllocation*)>;
90 static ResourceEstimator EstimateNoResources();
94 SimpleLoader(Creator creator, ResourceEstimator resource_estimator);
99 ResourceEstimator resource_estimator);
107 SimpleLoader(Creator creator, ResourceEstimator resource_estimator,
108 ResourceEstimator post_load_resource_estimator);
113 ResourceEstimator resource_estimator,
114 ResourceEstimator post_load_resource_estimator);
118 ResourceEstimator resource_estimator,
119 absl::optional<ResourceEstimator> post_load_resource_estimator);
127 Status
Load()
override;
136 Status EstimateResourcesPostLoad();
138 CreatorVariant creator_variant_;
141 ResourceEstimator resource_estimator_;
146 absl::optional<ResourceEstimator> post_load_resource_estimator_;
149 mutable absl::optional<ResourceAllocation> memoized_resource_estimate_
150 TF_GUARDED_BY(memoized_resource_estimate_mu_);
151 mutable mutex memoized_resource_estimate_mu_;
153 std::unique_ptr<ResourceUtil> resource_util_;
154 Resource ram_resource_;
156 std::unique_ptr<ServableType> servable_;
183 template <
typename DataType,
typename ServableType>
192 std::function<Status(
const DataType&, std::unique_ptr<ServableType>*)>;
196 using ResourceEstimator =
197 std::function<Status(
const DataType&, ResourceAllocation*)>;
206 static ResourceEstimator EstimateNoResources();
211 ResourceEstimator resource_estimator);
213 Status Convert(
const DataType& data, std::unique_ptr<Loader>* loader)
final;
217 ResourceEstimator resource_estimator_;
225 template <
typename ServableType>
226 typename SimpleLoader<ServableType>::ResourceEstimator
228 return [](ResourceAllocation* estimate) {
234 template <
typename ServableType>
235 SimpleLoader<ServableType>::SimpleLoader(Creator creator,
236 ResourceEstimator resource_estimator)
237 : SimpleLoader(CreatorVariant(creator), resource_estimator, absl::nullopt) {
240 template <
typename ServableType>
241 SimpleLoader<ServableType>::SimpleLoader(
242 CreatorWithMetadata creator_with_metadata,
243 ResourceEstimator resource_estimator)
244 : SimpleLoader(CreatorVariant(creator_with_metadata), resource_estimator,
247 template <
typename ServableType>
248 SimpleLoader<ServableType>::SimpleLoader(
249 Creator creator, ResourceEstimator resource_estimator,
250 ResourceEstimator post_load_resource_estimator)
251 : SimpleLoader(CreatorVariant(creator), resource_estimator,
252 {post_load_resource_estimator}) {}
254 template <
typename ServableType>
255 SimpleLoader<ServableType>::SimpleLoader(
256 CreatorWithMetadata creator_with_metadata,
257 ResourceEstimator resource_estimator,
258 ResourceEstimator post_load_resource_estimator)
259 : SimpleLoader(CreatorVariant(creator_with_metadata), resource_estimator,
260 {post_load_resource_estimator}) {}
262 template <
typename ServableType>
263 SimpleLoader<ServableType>::SimpleLoader(
264 CreatorVariant creator_variant, ResourceEstimator resource_estimator,
265 absl::optional<ResourceEstimator> post_load_resource_estimator)
266 : creator_variant_(creator_variant),
267 resource_estimator_(resource_estimator),
268 post_load_resource_estimator_(post_load_resource_estimator) {
269 ResourceUtil::Options resource_util_options;
270 resource_util_options.devices = {{device_types::kMain, 1}};
272 std::unique_ptr<ResourceUtil>(
new ResourceUtil(resource_util_options));
274 ram_resource_ = resource_util_->CreateBoundResource(
275 device_types::kMain, resource_kinds::kRamBytes);
278 template <
typename ServableType>
280 ResourceAllocation* estimate)
const {
281 mutex_lock l(memoized_resource_estimate_mu_);
282 if (memoized_resource_estimate_) {
283 *estimate = *memoized_resource_estimate_;
288 TF_RETURN_IF_ERROR(resource_estimator_(estimate));
289 memoized_resource_estimate_ = *estimate;
293 template <
typename ServableType>
295 if (absl::holds_alternative<CreatorWithMetadata>(creator_variant_)) {
296 return errors::FailedPrecondition(
297 "SimpleLoader::Load() called even though "
298 "SimpleLoader::CreatorWithMetadata was setup. Please use "
299 "SimpleLoader::LoadWithMetadata() instead.");
301 TF_RETURN_IF_ERROR(absl::get<Creator>(creator_variant_)(&servable_));
302 return EstimateResourcesPostLoad();
305 template <
typename ServableType>
307 if (absl::holds_alternative<CreatorWithMetadata>(creator_variant_)) {
309 absl::get<CreatorWithMetadata>(creator_variant_)(metadata, &servable_));
311 TF_RETURN_IF_ERROR(absl::get<Creator>(creator_variant_)(&servable_));
313 return EstimateResourcesPostLoad();
316 template <
typename ServableType>
318 if (post_load_resource_estimator_) {
320 ResourceAllocation during_load_resource_estimate;
321 TF_RETURN_IF_ERROR(EstimateResources(&during_load_resource_estimate));
324 ResourceAllocation post_load_resource_estimate;
326 (*post_load_resource_estimator_)(&post_load_resource_estimate));
328 mutex_lock l(memoized_resource_estimate_mu_);
329 memoized_resource_estimate_ = post_load_resource_estimate;
333 const uint64_t during_load_ram_estimate = resource_util_->GetQuantity(
334 ram_resource_, during_load_resource_estimate);
335 const uint64_t post_load_ram_estimate =
336 resource_util_->GetQuantity(ram_resource_, post_load_resource_estimate);
337 if (post_load_ram_estimate < during_load_ram_estimate) {
338 const uint64_t transient_ram_estimate =
339 during_load_ram_estimate - post_load_ram_estimate;
340 LOG(INFO) <<
"Calling MallocExtension_ReleaseToSystem() after servable "
342 << transient_ram_estimate;
343 ::tensorflow::port::MallocExtension_ReleaseToSystem(
344 transient_ram_estimate);
351 template <
typename ServableType>
355 ResourceAllocation resource_estimate;
356 Status resource_status = EstimateResources(&resource_estimate);
362 if (!resource_status.ok()) {
368 const uint64_t memory_estimate =
369 resource_util_->GetQuantity(ram_resource_, resource_estimate);
370 if (memory_estimate > 0) {
371 LOG(INFO) <<
"Calling MallocExtension_ReleaseToSystem() after servable "
374 ::tensorflow::port::MallocExtension_ReleaseToSystem(memory_estimate);
378 template <
typename DataType,
typename ServableType>
380 ServableType>::~SimpleLoaderSourceAdapter() {}
382 template <
typename DataType,
typename ServableType>
383 typename SimpleLoaderSourceAdapter<DataType, ServableType>::ResourceEstimator
384 SimpleLoaderSourceAdapter<DataType, ServableType>::EstimateNoResources() {
385 return [](
const DataType& data, ResourceAllocation* estimate) {
391 template <
typename DataType,
typename ServableType>
392 SimpleLoaderSourceAdapter<DataType, ServableType>::SimpleLoaderSourceAdapter(
393 Creator creator, ResourceEstimator resource_estimator)
394 : creator_(creator), resource_estimator_(resource_estimator) {}
396 template <
typename DataType,
typename ServableType>
397 Status SimpleLoaderSourceAdapter<DataType, ServableType>::Convert(
398 const DataType& data, std::unique_ptr<Loader>* loader) {
402 const auto creator = creator_;
403 const auto resource_estimator = resource_estimator_;
404 loader->reset(
new SimpleLoader<ServableType>(
405 [creator, data](std::unique_ptr<ServableType>* servable) {
406 return creator(data, servable);
408 [resource_estimator, data](ResourceAllocation* estimate) {
409 return resource_estimator(data, estimate);
Status EstimateResources(ResourceAllocation *estimate) const override
Status LoadWithMetadata(const Metadata &metadata) override
AnyPtr servable() override