// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. /** * This sample application demonstrates how to use components of the experimental C++ API * to query for model inputs/outputs and how to run inferrence on a model. * * This example is best run with one of the ResNet models (i.e. ResNet18) from the onnx model zoo at * https://github.com/onnx/models * * Assumptions made in this example: * 1) The onnx model has 1 input node and 1 output node * * * In this example, we do the following: * 1) read in an onnx model * 2) print out some metadata information about inputs and outputs that the model expects * 3) generate random data for an input tensor * 4) pass tensor through the model and check the resulting tensor * */ #include // std::generate #include #include #include #include #include // pretty prints a shape dimension vector std::string print_shape(const std::vector& v) { std::stringstream ss(""); for (size_t i = 0; i < v.size() - 1; i++) ss << v[i] << "x"; ss << v[v.size() - 1]; return ss.str(); } int calculate_product(const std::vector& v) { int total = 1; for (auto& i : v) total *= i; return total; } using namespace std; int main(int argc, char** argv) { if (argc != 2) { cout << "Usage: ./onnx-api-example " << endl; return -1; } #ifdef _WIN32 std::string str = argv[1]; std::wstring wide_string = std::wstring(str.begin(), str.end()); std::basic_string model_file = std::basic_string(wide_string); #else std::string model_file = argv[1]; #endif // onnxruntime setup Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "example-model-explorer"); Ort::SessionOptions session_options; Ort::Experimental::Session session = Ort::Experimental::Session(env, model_file, session_options); // access experimental components via the Experimental namespace // print name/shape of inputs std::vector input_names = session.GetInputNames(); std::vector > input_shapes = session.GetInputShapes(); cout << "Input Node Name/Shape (" << input_names.size() << "):" << endl; for (size_t i = 0; i < input_names.size(); i++) { cout << "\t" << input_names[i] << " : " << print_shape(input_shapes[i]) << endl; } // print name/shape of outputs std::vector output_names = session.GetOutputNames(); std::vector > output_shapes = session.GetOutputShapes(); cout << "Output Node Name/Shape (" << output_names.size() << "):" << endl; for (size_t i = 0; i < output_names.size(); i++) { cout << "\t" << output_names[i] << " : " << print_shape(output_shapes[i]) << endl; } // Assume model has 1 input node and 1 output node. assert(input_names.size() == 1 && output_names.size() == 1); // Create a single Ort tensor of random numbers auto input_shape = input_shapes[0]; int total_number_elements = calculate_product(input_shape); std::vector input_tensor_values(total_number_elements); std::generate(input_tensor_values.begin(), input_tensor_values.end(), [&] { return rand() % 255; }); // generate random numbers in the range [0, 255] std::vector input_tensors; input_tensors.push_back(Ort::Experimental::Value::CreateTensor(input_tensor_values.data(), input_tensor_values.size(), input_shape)); // double-check the dimensions of the input tensor assert(input_tensors[0].IsTensor() && input_tensors[0].GetTensorTypeAndShapeInfo().GetShape() == input_shape); cout << "\ninput_tensor shape: " << print_shape(input_tensors[0].GetTensorTypeAndShapeInfo().GetShape()) << endl; // pass data through model cout << "Running model..."; try { auto output_tensors = session.Run(session.GetInputNames(), input_tensors, session.GetOutputNames()); cout << "done" << endl; // double-check the dimensions of the output tensors // NOTE: the number of output tensors is equal to the number of output nodes specifed in the Run() call assert(output_tensors.size() == session.GetOutputNames().size() && output_tensors[0].IsTensor()); cout << "output_tensor_shape: " << print_shape(output_tensors[0].GetTensorTypeAndShapeInfo().GetShape()) << endl; } catch (const Ort::Exception& exception) { cout << "ERROR running model inference: " << exception.what() << endl; exit(-1); } }