Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion c_cxx/MNIST/MNIST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ struct MNIST {
const char* input_names[] = {"Input3"};
const char* output_names[] = {"Plus214_Output_0"};

session_.Run(Ort::RunOptions{nullptr}, input_names, &input_tensor_, 1, output_names, &output_tensor_, 1);
Ort::RunOptions run_options;
session_.Run(run_options, input_names, &input_tensor_, 1, output_names, &output_tensor_, 1);
softmax(results_);
result_ = std::distance(results_.begin(), std::max_element(results_.begin(), results_.end()));
return result_;
Expand Down
13 changes: 6 additions & 7 deletions c_cxx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ This directory contains a few C/C++ sample applications for demoing onnxruntime
## Prerequisites
1. Visual Studio 2015/2017/2019
2. cmake(version >=3.13)
3. (optional) [libpng 1.6](http://www.libpng.org/pub/png/libpng.html)

You may get a precompiled libpng library from [https://onnxruntimetestdata.blob.core.windows.net/models/libpng.zip](https://onnxruntimetestdata.blob.core.windows.net/models/libpng.zip)
3. (optional) [libpng 1.6](https://libpng.sourceforge.io/)

## Install ONNX Runtime
### Option 1: download a prebuilt package
Expand All @@ -31,16 +29,16 @@ build.bat --config RelWithDebInfo --build_shared_lib --parallel
By default this will build a project with "C:\Program Files (x86)\onnxruntime" install destination. This is a protected folder on Windows. If you do not want to run installation with elevated priviliges you will need to override the default installation location by passing extra CMake arguments. For example:

```
build.bat --config RelWithDebInfo --build_shared_lib --parallel --cmake_extra_defines CMAKE_INSTALL_PREFIX=c:\dev\ort_install
build.bat --config RelWithDebInfo --build_dir .\build --build_shared_lib --parallel --cmake_extra_defines CMAKE_INSTALL_PREFIX=c:\dev\ort_install
```

By default products of the build on Windows go to .\build\Windows\<config> folder. In the case above it would be .\build\Windows\RelWithDebInfo.
By default products of the build on Windows go to .\build\Windows\<config> folder. In the case above it would be .\build\RelWithDebInfo since the build folder is mentioned explicitly.
If you did not specify alternative installation location above you would need to open an elevated command prompt to install onnxruntime.
Run the following commands.

```
cd .\Windows\RelWithDebInfo
msbuild INSTALL.vcxproj /p:Configuration=RelWithDebInfo
cmake --install .\build\RelWithDebInfo --config RelWithDebInfo

```

## Build the samples
Expand All @@ -63,6 +61,7 @@ Or build it using msbuild

```bat
msbuild onnxruntime_samples.sln /p:Configuration=Debug|Release
cmake --install .\build\Debug|Release --config Debug
```

To run the samples make sure that your Install Folder Bin is in the path so your sample executable can find onnxruntime dll and libpng if you used it.
Expand Down
8 changes: 7 additions & 1 deletion c_cxx/imagenet/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Licensed under the MIT License.

set(FS_SOURCES local_filesystem.h sync_api.h controller.h controller.cc)

if(WIN32)
LIST(APPEND FS_SOURCES local_filesystem_win.cc sync_api_win.cc)
else()
Expand All @@ -17,17 +18,22 @@ if(JPEG_FOUND)
elseif(WIN32)
SET(IMAGE_SRC image_loader_wic.cc)
endif()

add_executable(image_classifier main.cc runnable_task.h data_processing.h ${IMAGE_SRC}
async_ring_buffer.h image_loader.cc image_loader.h cached_interpolation.h single_consumer.h)
async_ring_buffer.h image_loader.cc image_loader.h cached_interpolation.h single_consumer.h)

if(JPEG_FOUND)
target_compile_definitions(image_classifier PRIVATE HAVE_JPEG)
SET(IMAGE_HEADERS ${JPEG_INCLUDE_DIR})
SET(IMAGE_LIBS ${JPEG_LIBRARIES})
endif()

target_include_directories(image_classifier PRIVATE ${PROJECT_SOURCE_DIR}/include ${IMAGE_HEADERS})

if(WIN32)
target_compile_definitions(image_classifier PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX)
endif()

target_link_libraries(image_classifier PRIVATE onnxruntime slim_fs_lib ${IMAGE_LIBS})


Expand Down
2 changes: 1 addition & 1 deletion c_cxx/imagenet/image_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "cached_interpolation.h"
#include "sync_api.h"
#include "data_processing.h"
#include <onnxruntime_c_api.h>
#include <onnxruntime_cxx_api.h>

template <typename T>
void ResizeImageInMemory(const T* input_data, float* output_data, int in_height, int in_width, int out_height,
Expand Down
1 change: 1 addition & 0 deletions c_cxx/imagenet/local_filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <unistd.h>
#include <sys/mman.h>
#endif

#include <onnxruntime_c_api.h>
void ReadFileAsString(const ORTCHAR_T* fname, void*& p, size_t& len);

Expand Down
33 changes: 14 additions & 19 deletions c_cxx/imagenet/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
#include <vector>
#include <memory>
#include <atomic>
#include <optional>

#include "providers.h"
#include "local_filesystem.h"
#include "sync_api.h"
#include "providers.h"
#include "local_filesystem.h"
#include "sync_api.h"

#include <onnxruntime_cxx_api.h>

Expand All @@ -26,8 +27,10 @@
#ifdef _WIN32
#include <atlbase.h>
#endif

using namespace std::chrono;


class Validator : public OutputCollector<TCharString> {
private:
static std::vector<std::string> ReadFileToVec(const TCharString& file_path, size_t expected_line_count) {
Expand Down Expand Up @@ -81,20 +84,15 @@ class Validator : public OutputCollector<TCharString> {
int image_size_;

std::mutex m_;
char* input_name_ = nullptr;
char* output_name_ = nullptr;
std::optional<Ort::AllocatedStringPtr> input_name_;
std::optional<Ort::AllocatedStringPtr> output_name_;
Ort::Env& env_;
const TCharString model_path_;
system_clock::time_point start_time_;

public:
int GetImageSize() const { return image_size_; }

~Validator() {
free(input_name_);
free(output_name_);
}

void PrintResult() {
if (finished_count_ == 0) return;
printf("Top-1 Accuracy %f\n", ((float)top_1_correct_count_.load() / finished_count_));
Expand Down Expand Up @@ -124,20 +122,15 @@ class Validator : public OutputCollector<TCharString> {
VerifyInputOutputCount(session_);
Ort::AllocatorWithDefaultOptions ort_alloc;
{
char* t = session_.GetInputName(0, ort_alloc);
input_name_ = my_strdup(t);
ort_alloc.Free(t);
t = session_.GetOutputName(0, ort_alloc);
output_name_ = my_strdup(t);
ort_alloc.Free(t);
input_name_.emplace(session_.GetInputNameAllocated(0, ort_alloc));
output_name_.emplace(session_.GetOutputNameAllocated(0, ort_alloc));
}

Ort::TypeInfo info = session_.GetInputTypeInfo(0);
auto tensor_info = info.GetTensorTypeAndShapeInfo();
size_t dim_count = tensor_info.GetDimensionsCount();
assert(dim_count == 4);
std::vector<int64_t> dims(dim_count);
tensor_info.GetDimensions(dims.data(), dims.size());
std::vector<int64_t> dims = tensor_info.GetShape();
if (dims[1] != dims[2] || dims[3] != 3) {
throw std::runtime_error("This model is not supported by this program. input tensor need be in NHWC format");
}
Expand All @@ -150,8 +143,10 @@ class Validator : public OutputCollector<TCharString> {
{
std::lock_guard<std::mutex> l(m_);
const size_t remain = task_id_list.size();
const char* input_names[] = {input_name_->get()};
char* output_names[] = {output_name_->get()};
Ort::Value output_tensor{nullptr};
session_.Run(Ort::RunOptions{nullptr}, &input_name_, &input_tensor, 1, &output_name_, &output_tensor, 1);
session_.Run(Ort::RunOptions{nullptr}, input_names, &input_tensor, 1, output_names, &output_tensor, 1);
float* probs = output_tensor.GetTensorMutableData<float>();
for (const auto& s : task_id_list) {
float* end = probs + output_class_count_;
Expand Down
2 changes: 0 additions & 2 deletions c_cxx/imagenet/sync_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
#else
#include <vector>
#endif
#include <onnxruntime_c_api.h>
#include <onnxruntime_cxx_api.h>

#ifdef _WIN32
#define my_strtol wcstol
Expand Down
1 change: 1 addition & 0 deletions c_cxx/imagenet/sync_api_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

#include "sync_api.h"
#include <stdexcept>

void CreateAndSubmitThreadpoolWork(_In_ ONNXRUNTIME_CALLBACK_FUNCTION callback, _In_ void* data,
_In_opt_ PThreadPoolCallbackEnv pool) {
Expand Down
72 changes: 40 additions & 32 deletions c_cxx/squeezenet/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
//

#include <assert.h>
#include <vector>
#include <onnxruntime_cxx_api.h>

#include <iostream>
#include <vector>

#ifdef HAVE_TENSORRT_PROVIDER_FACTORY_H
#include <tensorrt_provider_factory.h>
#include <tensorrt_provider_options.h>
Expand Down Expand Up @@ -60,13 +62,15 @@ void run_ort_trt() {

//**************************************************************************************************************************
// It's suggested to use CreateTensorRTProviderOptions() to get provider options
// since ORT takes care of valid options for you
// since ORT takes care of valid options for you
//**************************************************************************************************************************
api.CreateTensorRTProviderOptions(&tensorrt_options);
std::unique_ptr<OrtTensorRTProviderOptionsV2, decltype(api.ReleaseTensorRTProviderOptions)> rel_trt_options(tensorrt_options, api.ReleaseTensorRTProviderOptions);
api.SessionOptionsAppendExecutionProvider_TensorRT_V2(static_cast<OrtSessionOptions*>(session_options), rel_trt_options.get());
std::unique_ptr<OrtTensorRTProviderOptionsV2, decltype(api.ReleaseTensorRTProviderOptions)> rel_trt_options(
tensorrt_options, api.ReleaseTensorRTProviderOptions);
api.SessionOptionsAppendExecutionProvider_TensorRT_V2(static_cast<OrtSessionOptions*>(session_options),
rel_trt_options.get());

printf("Runing ORT TRT EP with default provider options\n");
std::cout << "Running ORT TRT EP with default provider options" << std::endl;

Ort::Session session(env, model_path, session_options);

Expand All @@ -75,60 +79,69 @@ void run_ort_trt() {
Ort::AllocatorWithDefaultOptions allocator;

// print number of model input nodes
size_t num_input_nodes = session.GetInputCount();
std::vector<const char*> input_node_names(num_input_nodes);
const size_t num_input_nodes = session.GetInputCount();
std::vector<Ort::AllocatedStringPtr> input_names_ptr;
std::vector<const char*> input_node_names;
input_names_ptr.reserve(num_input_nodes);
input_node_names.reserve(num_input_nodes);
std::vector<int64_t> input_node_dims; // simplify... this model has only 1 input node {1, 3, 224, 224}.
// Otherwise need vector<vector<>>

printf("Number of inputs = %zu\n", num_input_nodes);
std::cout << "Number of inputs = " << num_input_nodes << std::endl;

// iterate over all input nodes
for (int i = 0; i < num_input_nodes; i++) {
for (size_t i = 0; i < num_input_nodes; i++) {
// print input node names
char* input_name = session.GetInputName(i, allocator);
printf("Input %d : name=%s\n", i, input_name);
input_node_names[i] = input_name;
auto input_name = session.GetInputNameAllocated(i, allocator);
std::cout << "Input " << i << " : name =" << input_name.get() << std::endl;
input_node_names.push_back(input_name.get());
input_names_ptr.push_back(std::move(input_name));

// print input node types
Ort::TypeInfo type_info = session.GetInputTypeInfo(i);
auto type_info = session.GetInputTypeInfo(i);
auto tensor_info = type_info.GetTensorTypeAndShapeInfo();

ONNXTensorElementDataType type = tensor_info.GetElementType();
printf("Input %d : type=%d\n", i, type);
std::cout << "Input " << i << " : type = " << type << std::endl;

// print input shapes/dims
input_node_dims = tensor_info.GetShape();
printf("Input %d : num_dims=%zu\n", i, input_node_dims.size());
for (size_t j = 0; j < input_node_dims.size(); j++)
printf("Input %d : dim %zu=%jd\n", i, j, input_node_dims[j]);
std::cout << "Input " << i << " : num_dims = " << input_node_dims.size() << '\n';
for (size_t j = 0; j < input_node_dims.size(); j++) {
std::cout << "Input " << i << " : dim[" << j << "] =" << input_node_dims[j] << '\n';
}
std::cout << std::flush;
}

size_t input_tensor_size = 224 * 224 * 3; // simplify ... using known dim values to calculate size
// use OrtGetTensorShapeElementCount() to get official size!
constexpr size_t input_tensor_size = 224 * 224 * 3; // simplify ... using known dim values to calculate size
// use OrtGetTensorShapeElementCount() to get official size!

std::vector<float> input_tensor_values(input_tensor_size);
std::vector<const char*> output_node_names = {"softmaxout_1"};

// initialize input data with values in [0.0, 1.0]
for (unsigned int i = 0; i < input_tensor_size; i++)
input_tensor_values[i] = (float)i / (input_tensor_size + 1);
for (unsigned int i = 0; i < input_tensor_size; i++) input_tensor_values[i] = (float)i / (input_tensor_size + 1);

// create input tensor object from data values
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_tensor_values.data(), input_tensor_size, input_node_dims.data(), 4);
auto input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_tensor_values.data(), input_tensor_size,
input_node_dims.data(), 4);
assert(input_tensor.IsTensor());

// score model & input tensor, get back output tensor
auto output_tensors = session.Run(Ort::RunOptions{nullptr}, input_node_names.data(), &input_tensor, 1, output_node_names.data(), 1);
auto output_tensors =
session.Run(Ort::RunOptions{nullptr}, input_node_names.data(), &input_tensor, 1, output_node_names.data(), 1);
assert(output_tensors.size() == 1 && output_tensors.front().IsTensor());

// Get pointer to output tensor float values
float* floatarr = output_tensors.front().GetTensorMutableData<float>();
assert(abs(floatarr[0] - 0.000045) < 1e-6);

// score the model, and print scores for first 5 classes
for (int i = 0; i < 5; i++)
printf("Score for class [%d] = %f\n", i, floatarr[i]);
for (int i = 0; i < 5; i++) {
std::cout << "Score for class [" << i << "] = " << floatarr[i] << '\n';
}
std::cout << std::flush;

// Results should be as below...
// Score for class[0] = 0.000045
Expand All @@ -137,15 +150,10 @@ void run_ort_trt() {
// Score for class[3] = 0.001180
// Score for class[4] = 0.001317


// release buffers allocated by ORT alloctor
for(const char* node_name : input_node_names)
allocator.Free(const_cast<void*>(reinterpret_cast<const void*>(node_name)));

printf("Done!\n");
std::cout << "Done!" << std::endl;
}

int main(int argc, char* argv[]) {
int main(int /*argc*/, char*[]) {
run_ort_trt();
return 0;
}