25 #include "ort_interface.hpp"
30 int CASADI_ONNX_ORT_EXPORT
35 plugin->version = CASADI_VERSION;
47 "Black-box ONNX model evaluation through Microsoft's ONNX Runtime.\n";
52 {
OT_STRING,
"Execution provider ('CPU', 'CUDA') [CPU]"}}
58 const std::vector<std::string>& inputs,
59 const std::vector<std::string>& outputs)
61 ort_api_(OrtGetApiBase()->GetApi(ORT_API_VERSION)), provider_(
"CPU") {
62 casadi_assert(ort_api_ !=
nullptr,
"Failed to obtain the ONNX Runtime API");
65 void OnnxRuntimeInterface::ort_check(OrtStatus* status,
const std::string& what)
const {
67 std::string msg = ort_api_->GetErrorMessage(status);
68 ort_api_->ReleaseStatus(status);
69 casadi_error(
"ONNX Runtime error (" + what +
"): " + msg);
72 void OnnxRuntimeInterface::build_prob() {
74 in_names_c_.clear(); out_names_c_.clear();
75 in_elem_.clear(); out_elem_.clear(); in_ndim_.clear(); out_ndim_.clear();
76 in_dims_.clear(); out_dims_.clear(); in_numel_.clear(); out_numel_.clear();
78 for (
const OnnxTensorInfo& t :
all_in_) {
79 in_names_c_.push_back(t.name.c_str());
80 in_elem_.push_back(t.elem_type);
81 in_ndim_.push_back(
static_cast<casadi_int
>(t.shape.size()));
82 for (casadi_int d : t.shape) in_dims_.push_back(d);
83 in_numel_.push_back(t.numel);
86 for (
const OnnxTensorInfo& t :
out_) {
87 out_names_c_.push_back(t.name.c_str());
88 out_elem_.push_back(t.elem_type);
89 out_ndim_.push_back(
static_cast<casadi_int
>(t.shape.size()));
90 for (casadi_int d : t.shape) out_dims_.push_back(d);
91 out_numel_.push_back(t.numel);
94 prob_.n_out =
out_.size();
95 prob_.input_names = in_names_c_.data();
96 prob_.output_names = out_names_c_.data();
99 prob_.in_elem_type = in_elem_.data();
100 prob_.out_elem_type = out_elem_.data();
101 prob_.in_ndim = in_ndim_.data();
102 prob_.out_ndim = out_ndim_.data();
103 prob_.in_dims = in_dims_.data();
104 prob_.out_dims = out_dims_.data();
105 prob_.in_numel = in_numel_.data();
106 prob_.out_numel = out_numel_.data();
108 prob_.model_size =
static_cast<casadi_int
>(
model_data_.size());
114 for (
auto&& op : opts) {
115 if (op.first ==
"provider") provider_ = op.second.to_string();
124 casadi_assert(casadi_onnxruntime_init(&m->d, &prob_) == 0,
125 "Failed to create ONNX Runtime session for '" +
name_ +
"'");
131 casadi_onnxruntime_data& d = m->
d;
134 for (casadi_int i = 0; i < prob_.n_in; ++i)
if (d.inv[i]) ort_api_->ReleaseValue(d.inv[i]);
138 for (casadi_int i = 0; i < prob_.n_in; ++i)
if (d.buf[i]) free(d.buf[i]);
144 if (d.mem) ort_api_->ReleaseMemoryInfo(d.mem);
145 if (d.session) ort_api_->ReleaseSession(d.session);
146 if (d.env) ort_api_->ReleaseEnv(d.env);
158 s.
version(
"OnnxRuntimeInterface", 1);
159 s.
pack(
"OnnxRuntimeInterface::provider", provider_);
164 ort_api_(OrtGetApiBase()->GetApi(ORT_API_VERSION)), provider_(
"CPU") {
165 casadi_assert(ort_api_ !=
nullptr,
"Failed to obtain the ONNX Runtime API");
166 s.
version(
"OnnxRuntimeInterface", 1);
167 s.
unpack(
"OnnxRuntimeInterface::provider", provider_);
172 casadi_int* iw,
double* w,
void* mem)
const {
174 return casadi_onnxruntime_solve(&m->d, &prob_, arg, res);
183 std::vector<std::string> in_nm, out_nm;
190 std::string in_elem = g.
constant(in_elem_), out_elem = g.
constant(out_elem_);
191 std::string in_ndim = g.
constant(in_ndim_), out_ndim = g.
constant(out_ndim_);
192 std::string in_dims = g.
constant(in_dims_.empty() ? std::vector<casadi_int>{0} : in_dims_);
193 std::string out_dims = g.
constant(out_dims_.empty() ? std::vector<casadi_int>{0} : out_dims_);
194 std::string in_numel = g.
constant(in_numel_), out_numel = g.
constant(out_numel_);
196 g <<
"static struct casadi_onnxruntime_prob prob = {"
198 << in_names <<
", " << out_names <<
", "
199 << in_src <<
", " << in_val <<
", "
200 << in_elem <<
", " << out_elem <<
", "
201 << in_ndim <<
", " << out_ndim <<
", "
202 << in_dims <<
", " << out_dims <<
", "
203 << in_numel <<
", " << out_numel <<
", "
204 <<
"(const unsigned char*)" << model <<
", " <<
model_data_.size() <<
"};\n";
205 g <<
"static struct casadi_onnxruntime_data data = {0};\n";
206 g <<
"if (casadi_onnxruntime_init(&data, &prob)) return 1;\n";
207 g <<
"return casadi_onnxruntime_solve(&data, &prob, arg, res);\n";
Helper class for C code generation.
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
void add_include(const std::string &new_include, bool relative_path=false, const std::string &use_ifdef=std::string())
Add an include file optionally using a relative path "..." instead of an absolute path <....
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
Internal class for GraphBuilder.
Black-box ONNX function base; backends (e.g. onnxruntime) derive from this.
std::vector< casadi_int > in_src_
Per all_in_ entry: exposed-arg index (>=0), -2 baked value, or -1 unwired (default)
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static const Options options_
Options.
std::vector< OnnxTensorInfo > out_
std::vector< OnnxTensorInfo > all_in_
Metadata for every model input (a runtime backend must feed all of them)
std::vector< uint8_t > model_data_
Serialized ONNX model.
std::vector< double > in_val_
Baked input values, flat over all_in_ (numel each; placeholder block when not baked)
void init(const Dict &opts) override
Initialize.
static const std::string meta_doc
Documentation.
int init_mem(void *mem) const override
Initialize memory block: create the ONNX Runtime session.
~OnnxRuntimeInterface() override
static OnnxFunction * creator(const std::string &name, const GraphBuilderInternal *gb, const std::vector< std::string > &inputs, const std::vector< std::string > &outputs, const Dict &opts)
Plugin factory.
void free_mem(void *mem) const override
Free memory block: tear down the session and reusable scaffolding.
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate numerically.
void init(const Dict &opts) override
Initialize.
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations.
static const Options options_
Options.
void codegen_body(CodeGenerator &g) const override
Generate code for the body.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into an OnnxRuntimeInterface.
OnnxRuntimeInterface(const std::string &name, const GraphBuilderInternal *gb, const std::vector< std::string > &inputs, const std::vector< std::string > &outputs)
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
virtual int init_mem(void *mem) const
Initalize memory block.
void clear_mem()
Clear all memory (called from destructor)
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
int CASADI_ONNX_ORT_EXPORT casadi_register_onnx_ort(OnnxFunction::Plugin *plugin)
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void CASADI_ONNX_ORT_EXPORT casadi_load_onnx_ort()
Per-checkout ONNX Runtime state (session + reusable eval scaffolding)
casadi_onnxruntime_data d
Metadata for a single ONNX tensor (input or output); shape is resolved by the builder.