Skip to content

Commit af1a960

Browse files
authored
ORT tutorials and samples (#529)
1 parent 7a635da commit af1a960

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+36097
-37
lines changed

c_cxx/README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
This directory contains a few C/C++ sample applications for demonstrating onnxruntime usage:
1+
# ORT Tutorials - C/C++ Samples
2+
3+
There is a suite of C/C++ samples in the [ort_tutorial directory](./ort_tutorial).
4+
All these samples are aimed to rely fully on cross vendor ONNX Runtime APIs, and should be able to run on any platform.
5+
Each sample show cases a specific feature of the ONNX Runtime API and illustrates how and why you should use it. The minimal ONNX Runtime version for these samples is 1.23.0.
6+
7+
## Other samples
8+
9+
This directory contains a few other C/C++ sample applications to demonstrate more specific onnxruntime usage:
210

311
1. (Windows and Linux) fns_candy_style_transfer: A C application that uses the FNS-Candy style transfer model to re-style images. It is written purely in C, no C++.
412
2. (Windows only) MNIST: A windows GUI application for doing handwriting recognition
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
project(winai-samples)
3+
4+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
5+
include(onnxruntimesetup)
6+
7+
add_executable(ep-device-selection
8+
main.cpp
9+
utils.cpp
10+
lodepng/lodepng.cpp
11+
)
12+
13+
set_target_properties(ep-device-selection PROPERTIES
14+
CXX_STANDARD 20
15+
CXX_EXTENSIONS OFF
16+
)
17+
target_link_libraries(ep-device-selection PRIVATE
18+
onnxruntime_interface
19+
)
20+
target_include_directories(ep-device-selection PRIVATE
21+
lode_png
22+
)
23+
24+
set(DEPTH_ANYTHING_FP16_ONNX "depth_anything_v2_torch.float16_240.onnx")
25+
26+
copy_file_to_bin_dir(${DEPTH_ANYTHING_FP16_ONNX})
27+
copy_file_to_bin_dir(Input.png)
28+
29+
target_compile_definitions(ep-device-selection
30+
PRIVATE -DMODEL_FILE="${DEPTH_ANYTHING_FP16_ONNX}")
31+
set_target_properties(ep-device-selection
32+
PROPERTIES
33+
ARCHIVE_OUTPUT_DIRECTORY "${RUNTIME_DIRECTORY}"
34+
LIBRARY_OUTPUT_DIRECTORY "${RUNTIME_DIRECTORY}"
35+
RUNTIME_OUTPUT_DIRECTORY "${RUNTIME_DIRECTORY}"
36+
)
1.18 MB
Loading
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# EP Device Selection
2+
3+
ONNX Runtime provides since version 1.23.0 an execution provider independent way of querying and selecting
4+
inference devices. This involves typically 3 steps.
5+
6+
- 1. Registration of execution provider libraries
7+
```cpp
8+
auto env = Ort::Env(ORT_LOGGING_LEVEL_WARNING);
9+
env.RegisterExecutionProviderLibrary("openvino", ORT_TSTR("onnxruntime_providers_openvino.dll"));
10+
env.RegisterExecutionProviderLibrary("qnn", ORT_TSTR("onnxruntime_providers_qnn.dll"));
11+
env.RegisterExecutionProviderLibrary("nv_tensorrt_rtx", ORT_TSTR("onnxruntime_providers_nv_tensorrt_rtx.dll"));
12+
```
13+
14+
- 2. Querying and selecting Execution Provider (EP) Devices
15+
16+
```cpp
17+
auto ep_devices = env.GetEpDevices();
18+
auto selected_devices = my_ep_selection_function(ep_devices);
19+
20+
Ort::SessionOptions session_options;
21+
session_options.AppendExecutionProvider_V2(env, selected_devices, ep_options);
22+
// Optionally, set device policy. E.g. OrtExecutionProviderDevicePolicy_PREFER_GPU, OrtExecutionProviderDevicePolicy_PREFER_NPU, OrtExecutionProviderDevicePolicy_MAX_PERFORMANCE
23+
session_options.SetEpSelectionPolicy(OrtExecutionProviderDevicePolicy_PREFER_GPU);
24+
```
25+
- 3. Use the session options to create a inference session
26+
27+
```cpp
28+
Ort::Session session(env, ORT_TSTR("path/to/model.onnx"), session_options);
29+
```
30+
31+
32+
## Building the sample
33+
34+
`cmake -B build -S . -DONNX_RUNTIME_PATH=path/to/onnxruntime> -DTRTRTX_RUNTIME_PATH=<path/to/TRTRTX/libs> && cmake --build build --config Release`
35+
36+
Then run
37+
```
38+
./build/Release/ep-device-selection -i ./Input.png -o ./output.png
39+
```
40+
41+
Run
42+
43+
```
44+
./build/Release/ep-device-selection -h
45+
```
46+
to know about more available command line options that influence device selection.
47+
48+
## Model
49+
50+
The ONNX file in this folder was generated using code from https://github.com/DepthAnything/Depth-Anything-V2 (Apache 2.0)
51+
with weights from https://huggingface.co/depth-anything/Depth-Anything-V2-Small/ (Apache 2.0).
52+
53+
## Dependencies
54+
55+
This sample vendors a copy of https://github.com/lvandeve/lodepng (Zlib license)
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#pragma once
2+
3+
#include "utils.h"
4+
5+
#include <onnxruntime/core/graph/constants.h>
6+
#include <onnxruntime/core/session/onnxruntime_cxx_api.h>
7+
8+
#include <filesystem>
9+
#include <functional>
10+
#include <string>
11+
#include <string_view>
12+
13+
struct Opts {
14+
std::string input_image;
15+
std::string output_image;
16+
std::string select_vendor;
17+
std::string select_ep;
18+
bool enableEpContext{true};
19+
OrtExecutionProviderDevicePolicy ep_device_policy =
20+
OrtExecutionProviderDevicePolicy_PREFER_GPU;
21+
};
22+
23+
struct ArgumentSpec {
24+
const char *name;
25+
const char *short_name;
26+
const char *help;
27+
int num_args;
28+
std::function<bool(int)> lambda;
29+
};
30+
31+
static Opts parse_args(int argc, char **argv) {
32+
using namespace std::string_view_literals;
33+
Opts opts;
34+
auto arg_specs = std::array{
35+
// clang-format off
36+
ArgumentSpec{
37+
"--input", "-i", "Path to input image (*.png)", 1, [&](int i) {
38+
opts.input_image = argv[i + 1];
39+
if (opts.input_image.starts_with("-")) {
40+
LOG("Path to input image can't start with -: \"{}\"",
41+
opts.input_image.c_str());
42+
return false;
43+
}
44+
return true;
45+
}},
46+
ArgumentSpec{
47+
"--output", "-o", "Path where to save output image (*.png)", 1, [&](int i) {
48+
opts.output_image = argv[i + 1];
49+
if (opts.output_image.starts_with("-")) {
50+
LOG("Path to output image can't start with -: \"{}\"",
51+
opts.output_image.c_str());
52+
return false;
53+
}
54+
return true;
55+
}},
56+
ArgumentSpec{
57+
"--select-vendor", "-f", "Select device of provided vendor.", 1, [&](int i) {
58+
opts.select_vendor = argv[i + 1];
59+
if (opts.select_vendor.starts_with("-")) {
60+
LOG("Vendor can't start with -: \"{}\"",
61+
opts.select_vendor.c_str());
62+
return false;
63+
}
64+
return true;
65+
}},
66+
ArgumentSpec{
67+
"--select-ep", "-f", "Select devices that support a specific execution provider. "
68+
"See https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/graph/constants.h for EP names."
69+
, 1, [&](int i) {
70+
opts.select_vendor = argv[i + 1];
71+
if (opts.select_vendor.starts_with("-")) {
72+
LOG("Execution provider can't start with -: \"{}\"",
73+
opts.select_vendor.c_str());
74+
return false;
75+
}
76+
return true;
77+
}},
78+
ArgumentSpec{
79+
"--ep-device-policy", "-p", "Set a EP device policy: e.g. prefer-cpu, prefer-gpu, prefer-npu, max-performance, max-efficiency, min-overall-power", 1, [&](int i) {
80+
if(argv[i+1] == "prefer-cpu"sv) {
81+
opts.ep_device_policy = OrtExecutionProviderDevicePolicy_PREFER_CPU;
82+
} else if(argv[i+1] == "prefer-gpu"sv) {
83+
opts.ep_device_policy = OrtExecutionProviderDevicePolicy_PREFER_GPU;
84+
} else if(argv[i+1] == "prefer-npu"sv) {
85+
opts.ep_device_policy = OrtExecutionProviderDevicePolicy_PREFER_NPU;
86+
} else if(argv[i+1] == "max-performance"sv) {
87+
opts.ep_device_policy = OrtExecutionProviderDevicePolicy_MAX_PERFORMANCE;
88+
} else if(argv[i+1] == "max-efficiency"sv) {
89+
opts.ep_device_policy = OrtExecutionProviderDevicePolicy_MAX_EFFICIENCY;
90+
} else if(argv[i+1] == "min-overall-power"sv) {
91+
opts.ep_device_policy = OrtExecutionProviderDevicePolicy_MIN_OVERALL_POWER;
92+
} else {
93+
LOG("Invalid execution provider policy: \"{}\"! Choose among prefer-cpu, prefer-gpu, prefer-npu, max-performance, max-efficiency, min-overall-power", argv[i+1]);
94+
return false;
95+
}
96+
return true;
97+
}}
98+
// clang-format on
99+
};
100+
auto print_usage = [&] {
101+
LOG("");
102+
LOG("Usage:");
103+
LOG("{} <options>", argv[0]);
104+
for (auto &spec : arg_specs) {
105+
if (spec.short_name) {
106+
LOG("\t{} {} {}", spec.name, spec.short_name, spec.help);
107+
} else {
108+
LOG("\t{} {}", spec.name, spec.help);
109+
}
110+
}
111+
};
112+
for (int i = 1; i < argc; i++) {
113+
bool arg_found = false;
114+
for (auto &spec : arg_specs) {
115+
if (std::strcmp(spec.name, argv[i]) == 0 ||
116+
(spec.short_name && std::strcmp(spec.short_name, argv[i]) == 0)) {
117+
if (i + spec.num_args < argc) {
118+
bool ok = spec.lambda(i);
119+
if (!ok) {
120+
LOG("Failed to parse arguments for {}!", spec.name);
121+
exit(EXIT_FAILURE);
122+
}
123+
arg_found = true;
124+
i += spec.num_args;
125+
break;
126+
} else {
127+
LOG("Not enough arguments for {} specified!", spec.name);
128+
exit(EXIT_FAILURE);
129+
}
130+
}
131+
}
132+
if (!arg_found) {
133+
auto arg = argv[i];
134+
LOG("Unknown argument: {}", arg);
135+
print_usage();
136+
exit(EXIT_FAILURE);
137+
}
138+
}
139+
if (opts.input_image.empty()) {
140+
opts.input_image = (get_executable_path().parent_path() / "Input.png").string();
141+
}
142+
if (opts.output_image.empty()) {
143+
opts.output_image = (get_executable_path().parent_path() / "output.png").string();
144+
}
145+
if (!std::filesystem::is_regular_file(opts.input_image)) {
146+
LOG("Please make sure that provided input image path exists: \"{}\"!",
147+
opts.input_image.c_str());
148+
print_usage();
149+
exit(EXIT_FAILURE);
150+
}
151+
if (!std::filesystem::is_directory(
152+
std::filesystem::path(opts.output_image).parent_path())) {
153+
LOG("Please make sure that the parent directory of the provided output "
154+
"path exists: \"{}\"!",
155+
opts.output_image.c_str());
156+
print_usage();
157+
exit(EXIT_FAILURE);
158+
}
159+
return opts;
160+
}

0 commit comments

Comments
 (0)