source/neuropod/backends/neuropod_backend.hh (66 lines of code) (raw):
/* Copyright (c) 2020 The Neuropod Authors
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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include "neuropod/backends/tensor_allocator.hh"
#include "neuropod/internal/backend_registration.hh"
#include "neuropod/internal/deleter.hh"
#include "neuropod/internal/neuropod_loader.hh"
#include "neuropod/internal/neuropod_tensor.hh"
#include "neuropod/internal/tensor_types.hh"
#include <memory>
#include <mutex>
#include <string>
#include <unordered_set>
#include <vector>
namespace neuropod
{
class Sealer
{
private:
// A mapping from tensor name to device
std::unordered_map<std::string, NeuropodDevice> device_mapping_;
public:
Sealer(std::unordered_map<std::string, NeuropodDevice> device_mapping);
~Sealer();
std::shared_ptr<NeuropodValue> seal(const std::string &name, const std::shared_ptr<NeuropodValue> &value);
// Seal every item in the map
NeuropodValueMap seal(const NeuropodValueMap &inputs);
};
// The interface that every neuropod backend implements
class NeuropodBackend
{
public:
NeuropodBackend(const std::string &neuropod_path, RuntimeOptions options);
virtual ~NeuropodBackend();
// Returns an allocator that can allocate tensors compatible with this backend
virtual std::shared_ptr<NeuropodTensorAllocator> get_tensor_allocator() = 0;
// Run inference and get a subset of the outputs
std::unique_ptr<NeuropodValueMap> infer(const NeuropodValueMap & inputs,
const std::vector<std::string> &requested_outputs = {});
// Get the inputs and outputs of this model
const std::vector<TensorSpec> &get_inputs() const;
const std::vector<TensorSpec> &get_outputs() const;
// Get the name of this model.
const std::string &get_name() const;
// Get the platform of this model.
const std::string &get_platform() const;
// Load the model if it has not already been loaded
void load_model();
protected:
// Used to load files in a Neuropod
std::unique_ptr<NeuropodLoader> loader_;
// The neuropod model config
std::unique_ptr<ModelConfig> model_config_;
// The neuropod path (if one was provided in the constructor)
std::string neuropod_path_;
// The options this model was loaded with
RuntimeOptions options_;
// Run inference and get a subset of the outputs
// The default implementation runs inference, gets all the outputs, and then filters the outputs
// Backends can override this to more efficiently generate only the requested outputs
virtual std::unique_ptr<NeuropodValueMap> infer_internal(const NeuropodValueMap & inputs,
const std::vector<std::string> &requested_outputs);
// Run inference
// Backends must provide an implementation of infer_internal (either this signature or the one above)
virtual std::unique_ptr<NeuropodValueMap> infer_internal(const NeuropodValueMap &inputs);
// A method that loads the underlying model
virtual void load_model_internal() = 0;
private:
// Whether or not the underlying model has already been loaded
bool is_model_loaded_ = false;
std::unique_ptr<Sealer> sealer_;
};
template <template <class> class TensorImpl>
class NeuropodBackendWithDefaultAllocator : public NeuropodBackend
{
private:
std::shared_ptr<NeuropodTensorAllocator> allocator_;
public:
NeuropodBackendWithDefaultAllocator(const std::string &neuropod_path, const RuntimeOptions &options)
: NeuropodBackend(neuropod_path, options), allocator_(std::make_shared<DefaultTensorAllocator<TensorImpl>>())
{
}
std::shared_ptr<NeuropodTensorAllocator> get_tensor_allocator() { return allocator_; }
};
// A utility for validating tensors against a vector of specs. Throws an error if validation fails
// Note: This function is exposed in order to properly unit test it and should not be directly used
void validate_tensors_against_specs(const NeuropodValueMap & tensors,
const std::vector<TensorSpec> &specs,
const std::string & debug_spec_name = "spec");
} // namespace neuropod