file src/onnx_rt_wrapper.cpp
[No description available] More…
Namespaces
| Name |
|---|
| Gambit TODO: see if we can use this one: |
| Gambit::ColliderBit |
Detailed Description
Author: Tomasz Procter
Date: 2023 August
Wrapper class for interfacing to ONNXRunTime
Authors (add name and date if you modify):
Source code
// GAMBIT: Global and Modular BSM Inference Tool
// *********************************************
/// \file
///
/// Wrapper class for interfacing to ONNXRunTime
///
/// *********************************************
///
/// Authors (add name and date if you modify):
///
/// \author Tomasz Procter
/// \date 2023 August
///
/// *********************************************
#include "gambit/cmake/cmake_variables.hpp"
#ifndef EXCLUDE_ONNXRUNTIME
#include "gambit/ColliderBit/onnx_rt_wrapper.hpp"
#include <ostream>
using namespace std;
namespace Gambit
{
namespace ColliderBit
{
onnx_rt_wrapper::onnx_rt_wrapper(const string & filename, const string& runname)
{
// Set some ORT variables that need to be kept in memory
_env = std::make_unique<Ort::Env>(ORT_LOGGING_LEVEL_WARNING,runname.c_str() );
Ort::SessionOptions sessionopts; //todo - check this is allowed to go out of scope.
_session = std::make_unique<Ort::Session> (*_env, filename.c_str(), sessionopts);
// Get network hyper-params and store them (input, output shape, etc.) in the class members.
getNetworkInfo();
}
/// Given a multi-node input vector, populate and return the multi-node output vector
void onnx_rt_wrapper::compute(std::vector<std::vector<float>> &inputs, std::vector<std::vector<float>>& outputs) const
{
/// Check that number of input nodes matches what the model expects
if (inputs.size() != _inDims.size())
{
throw("Expected " + to_string(_inDims.size())
+ " input nodes, received " + to_string(inputs.size()));
}
// Create input tensor objects from input data
vector<Ort::Value> ort_input;
ort_input.reserve(_inDims.size());
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
for (size_t i=0; i < _inDims.size(); ++i)
{
// Check that input data matches expected input node dimension
if (inputs[i].size() != (size_t) _inDimsFlat[i])
{
throw("Expected flattened input node dimension " + to_string(_inDimsFlat[i])
+ ", received " + to_string(inputs[i].size()));
}
ort_input.emplace_back(Ort::Value::CreateTensor<float>(memory_info,
inputs[i].data(), inputs[i].size(),
_inDims[i].data(), _inDims[i].size()));
}
// Retrieve output tensors
auto ort_output = _session->Run(Ort::RunOptions{nullptr}, _inNames.data(),
ort_input.data(), ort_input.size(),
_outNames.data(), _outNames.size());
// Construct flattened values and return
outputs.clear();
outputs.resize(_outDims.size());
for (size_t i = 0; i < _outDims.size(); ++i)
{
float* floatarr = ort_output[i].GetTensorMutableData<float>();
outputs[i].assign(floatarr, floatarr + _outDimsFlat[i]);
}
}
/// Given a single-node input vector, populate and return the single-node output vector
void onnx_rt_wrapper::compute(vector<float>& inputs, vector<float> & outputs)
{
if (_inDims.size() != 1 || _outDims.size() != 1)
{
throw("This method assumes a single input/output node!");
}
vector<vector<float>> wrapped_inputs = { inputs };
vector<vector<float>> wrapped_outputs;
compute(wrapped_inputs, wrapped_outputs);
outputs = wrapped_outputs[0];
}
/// Printing function for debugging.
std::ostream& operator <<(std::ostream& os, const onnx_rt_wrapper& rort)
{
os << "RivetONNXrt Network Summary: \n";
for (size_t i=0; i < rort._inNames.size(); ++i)
{
os << "- Input node " << i << " name: " << rort._inNames[i];
os << ", dimensions: (";
for (size_t j=0; j < rort._inDims[i].size(); ++j)
{
if (j) os << ", ";
os << rort._inDims[i][j];
}
os << "), type (as ONNX enums): " << rort._inTypes[i] << "\n";
}
for (size_t i=0; i < rort._outNames.size(); ++i)
{
os << "- Output node " << i << " name: " << rort._outNames[i];
os << ", dimensions: (";
for (size_t j=0; j < rort._outDims[i].size(); ++j)
{
if (j) os << ", ";
os << rort._outDims[i][j];
}
os << "), type (as ONNX enums): (" << rort._outTypes[i] << "\n";
}
return os;
}
// Check the ONNX file to get hyperparameters etc.
void onnx_rt_wrapper::getNetworkInfo()
{
Ort::AllocatorWithDefaultOptions allocator;
// Retrieve network metadat
_metadata = std::make_unique<Ort::ModelMetadata>(_session->GetModelMetadata());
// Find out how many input nodes the model expects
const size_t num_input_nodes = _session->GetInputCount();
_inDimsFlat.reserve(num_input_nodes);
_inTypes.reserve(num_input_nodes);
_inDims.reserve(num_input_nodes);
_inNames.reserve(num_input_nodes);
_inNamesPtr.reserve(num_input_nodes);
for (size_t i = 0; i < num_input_nodes; ++i)
{
// Retrieve input node name
auto input_name = _session->GetInputNameAllocated(i, allocator);
_inNames.push_back(input_name.get());
_inNamesPtr.push_back(std::move(input_name));
// Retrieve input node type
auto in_type_info = _session->GetInputTypeInfo(i);
auto in_tensor_info = in_type_info.GetTensorTypeAndShapeInfo();
_inTypes.push_back(in_tensor_info.GetElementType());
_inDims.push_back(in_tensor_info.GetShape());
}
// Fix negative shape values - appears to be an artefact of batch size issues.
for (auto& dims : _inDims)
{
int64_t n = 1;
for (auto& dim : dims)
{
if (dim < 0) dim = abs(dim);
n *= dim;
}
_inDimsFlat.push_back(n);
}
// Find out how many output nodes the model expects
const size_t num_output_nodes = _session->GetOutputCount();
_outDimsFlat.reserve(num_output_nodes);
_outTypes.reserve(num_output_nodes);
_outDims.reserve(num_output_nodes);
_outNames.reserve(num_output_nodes);
_outNamesPtr.reserve(num_output_nodes);
for (size_t i = 0; i < num_output_nodes; ++i)
{
// Retrieve output node name
auto output_name = _session->GetOutputNameAllocated(i, allocator);
_outNames.push_back(output_name.get());
_outNamesPtr.push_back(std::move(output_name));
// Retrieve input node type
auto out_type_info = _session->GetOutputTypeInfo(i);
auto out_tensor_info = out_type_info.GetTensorTypeAndShapeInfo();
_outTypes.push_back(out_tensor_info.GetElementType());
_outDims.push_back(out_tensor_info.GetShape());
}
// Fix negative shape values - appears to be an artefact of batch size issues.
for (auto& dims : _outDims)
{
int64_t n = 1;
for (auto& dim : dims)
{
if (dim < 0) dim = abs(dim);
n *= dim;
}
_outDimsFlat.push_back(n);
}
}
}
}
#endif
Updated on 2026-11-03 at 14:50:48 +0000