Skip to content
Open
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
137 changes: 75 additions & 62 deletions SerialPrograms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -379,74 +379,87 @@ else() # macOS and Linux
# extract it, and then link it up

# Set the ONNXRUNTIME version and arch, allows for quick updates
set(ONNXRUNTIME_VERSION "1.23.0")
set(ONNXRUNTIME_ARCH "x64")
set(ONNXRUNTIME_DIR_NAME "onnxruntime-linux-${ONNXRUNTIME_ARCH}-${ONNXRUNTIME_VERSION}")
set(ONNXRUNTIME_TGZ_NAME "${ONNXRUNTIME_DIR_NAME}.tgz")
# build up the URL based on the version and name
set(ONNXRUNTIME_URL "https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/${ONNXRUNTIME_TGZ_NAME}")

# Cache variable is editable by users *and* is properly stored
set(ONNX_ROOT_PATH "" CACHE PATH "Path to the root of a pre-installed ONNX Runtime (e.g., /path/to/onnxruntime-linux-x64-1.23.0)")

# Download the onnxruntime if it doesn't exist or if the path is bad
if(NOT ONNX_ROOT_PATH OR NOT EXISTS "${ONNX_ROOT_PATH}/include/onnxruntime_cxx_api.h")
set(EXTRACTED_ONNX_PATH "${CMAKE_BINARY_DIR}/${ONNXRUNTIME_DIR_NAME}")

if(NOT IS_DIRECTORY ${EXTRACTED_ONNX_PATH})
message(STATUS "ONNX_ROOT_PATH not found. Downloading ONNX Runtime v${ONNXRUNTIME_VERSION}...")

# logic for downloading...
set(DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/${ONNXRUNTIME_TGZ_NAME}")
file(DOWNLOAD
${ONNXRUNTIME_URL}
${DOWNLOAD_LOCATION}
SHOW_PROGRESS
STATUS download_status
)
list(GET download_status 0 error_code)
if(NOT error_code EQUAL 0)
list(GET download_status 1 error_message)
message(FATAL_ERROR "Failed to download ONNX Runtime: ${error_message}")
endif()
pkg_check_modules(ONNXRUNTIME QUIET libonnxruntime)

# logic for extracting the tarball to our working directory
message(STATUS "Extracting ONNX Runtime...")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xzf "${DOWNLOAD_LOCATION}"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
endif()
if(ONNXRUNTIME_FOUND)
message(STATUS "Found system installed ONNX Runtime")

message(STATUS "Found ONNX Include Dirs: ${ONNXRUNTIME_INCLUDE_DIRS}")
message(STATUS "Found ONNX Library: ${ONNXRUNTIME_LIBRARIES}")

target_include_directories(SerialProgramsLib PUBLIC ${ONNXRUNTIME_INCLUDE_DIRS})
target_link_libraries(SerialProgramsLib PUBLIC ${ONNXRUNTIME_LIBRARIES})

# Update the ONNX_ROOT_PATH to point to our downloaded version, force ensures we update it
set(ONNX_ROOT_PATH "${EXTRACTED_ONNX_PATH}" CACHE PATH "Path to the downloaded ONNX Runtime" FORCE)
message(STATUS "Using downloaded ONNX Runtime at: ${ONNX_ROOT_PATH}")
else()
message(STATUS "Using user-provided ONNX Runtime at: ${ONNX_ROOT_PATH}")
endif()
set(ONNXRUNTIME_VERSION "1.23.0")
set(ONNXRUNTIME_ARCH "x64")
set(ONNXRUNTIME_DIR_NAME "onnxruntime-linux-${ONNXRUNTIME_ARCH}-${ONNXRUNTIME_VERSION}")
set(ONNXRUNTIME_TGZ_NAME "${ONNXRUNTIME_DIR_NAME}.tgz")
# build up the URL based on the version and name
set(ONNXRUNTIME_URL "https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/${ONNXRUNTIME_TGZ_NAME}")

# Cache variable is editable by users *and* is properly stored
set(ONNX_ROOT_PATH "" CACHE PATH "Path to the root of a pre-installed ONNX Runtime (e.g., /path/to/onnxruntime-linux-x64-1.23.0)")

# Download the onnxruntime if it doesn't exist or if the path is bad
if(NOT ONNX_ROOT_PATH OR NOT EXISTS "${ONNX_ROOT_PATH}/include/onnxruntime_cxx_api.h")
set(EXTRACTED_ONNX_PATH "${CMAKE_BINARY_DIR}/${ONNXRUNTIME_DIR_NAME}")

if(NOT IS_DIRECTORY ${EXTRACTED_ONNX_PATH})
message(STATUS "ONNX_ROOT_PATH not found. Downloading ONNX Runtime v${ONNXRUNTIME_VERSION}...")

# logic for downloading...
set(DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/${ONNXRUNTIME_TGZ_NAME}")
file(DOWNLOAD
${ONNXRUNTIME_URL}
${DOWNLOAD_LOCATION}
SHOW_PROGRESS
STATUS download_status
)
list(GET download_status 0 error_code)
if(NOT error_code EQUAL 0)
list(GET download_status 1 error_message)
message(FATAL_ERROR "Failed to download ONNX Runtime: ${error_message}")
endif()

# logic for extracting the tarball to our working directory
message(STATUS "Extracting ONNX Runtime...")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xzf "${DOWNLOAD_LOCATION}"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
endif()

# configure and find headers from the onnxruntime
find_path(ONNX_INCLUDE_DIRS
NAMES onnxruntime_cxx_api.h
HINTS "${ONNX_ROOT_PATH}/include"
REQUIRED
)
# Update the ONNX_ROOT_PATH to point to our downloaded version, force ensures we update it
set(ONNX_ROOT_PATH "${EXTRACTED_ONNX_PATH}" CACHE PATH "Path to the downloaded ONNX Runtime" FORCE)
message(STATUS "Using downloaded ONNX Runtime at: ${ONNX_ROOT_PATH}")
else()
message(STATUS "Using user-provided ONNX Runtime at: ${ONNX_ROOT_PATH}")
endif()

find_library(ONNX_RUNTIME_LIB
NAMES onnxruntime
HINTS "${ONNX_ROOT_PATH}/lib"
REQUIRED
)
# configure and find headers from the onnxruntime
find_path(ONNX_INCLUDE_DIRS
NAMES onnxruntime_cxx_api.h
HINTS "${ONNX_ROOT_PATH}/include"
REQUIRED
)

if(ONNX_INCLUDE_DIRS AND ONNX_RUNTIME_LIB)
# only link if it was found, otherwise we error out
message(STATUS "Found ONNX Include Dirs: ${ONNX_INCLUDE_DIRS}")
message(STATUS "Found ONNX Library: ${ONNX_RUNTIME_LIB}")
target_include_directories(SerialProgramsLib PUBLIC "${ONNX_INCLUDE_DIRS}")
target_link_libraries(SerialProgramsLib PUBLIC "${ONNX_RUNTIME_LIB}")
else()
message(FATAL_ERROR "Could not find ONNX Runtime headers or library.")
endif()
find_library(ONNX_RUNTIME_LIB
NAMES onnxruntime
HINTS "${ONNX_ROOT_PATH}/lib"
REQUIRED
)

if(ONNX_INCLUDE_DIRS AND ONNX_RUNTIME_LIB)
# only link if it was found, otherwise we error out
message(STATUS "Found ONNX Include Dirs: ${ONNX_INCLUDE_DIRS}")
message(STATUS "Found ONNX Library: ${ONNX_RUNTIME_LIB}")
target_include_directories(SerialProgramsLib PUBLIC "${ONNX_INCLUDE_DIRS}")
target_link_libraries(SerialProgramsLib PUBLIC "${ONNX_RUNTIME_LIB}")
else()
message(FATAL_ERROR "Could not find ONNX Runtime headers or library.")
endif()
endif ()
endif() # end Linux

# Find OpenCV
Expand Down
44 changes: 41 additions & 3 deletions SerialPrograms/Source/ML/Models/ML_ONNXRuntimeHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,54 @@ if (use_gpu){
std::cout << "CUDA execution provider not available: " << e.what() << std::endl;
}

bool rocm_available = false;
if (!cuda_available) {
// Try ROCm next for AMD GPUs
// See: https://onnxruntime.ai/docs/execution-providers/ROCm-ExecutionProvider.html
try {
OrtROCMProviderOptions rocm_options{};
rocm_options.device_id = 0;
so.AppendExecutionProvider_ROCM(rocm_options);
std::cout << "Using ROCm execution provider for GPU acceleration" << std::endl;
rocm_available = true;
} catch (const Ort::Exception& e) {
std::cout << "ROCm execution provider not available, falling back to CPU: " << e.what() << std::endl;
}
}

// Fallback to DirectML for all GPU vendors (NVIDIA, AMD, Intel)
// DirectML is built into Windows 10 1903+ and requires no additional runtime installation
// See: https://onnxruntime.ai/docs/execution-providers/DirectML-ExecutionProvider.html
if (!cuda_available){
if (!cuda_available and !rocm_available){
try {
so.AppendExecutionProvider("DML");
std::cout << "Using DirectML execution provider for GPU acceleration" << std::endl;
} catch (const Ort::Exception& e){
std::cout << "DirectML execution provider not available, falling back to CPU: " << e.what() << std::endl;
}
}
#elif defined(__linux__)
// Try CUDA first for NVIDIA GPUs (best performance)
// See: https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html
try {
OrtCUDAProviderOptions cuda_options{};
cuda_options.device_id = 0;
so.AppendExecutionProvider_CUDA(cuda_options);
std::cout << "Using CUDA execution provider for GPU acceleration" << std::endl;
} catch (const Ort::Exception& e) {
std::cout << "CUDA execution provider not available, trying ROCm: " << e.what() << std::endl;

// Try ROCm next for AMD GPUs
// See: https://onnxruntime.ai/docs/execution-providers/ROCm-ExecutionProvider.html
try {
OrtROCMProviderOptions rocm_options{};
rocm_options.device_id = 0;
so.AppendExecutionProvider_ROCM(rocm_options);
std::cout << "Using ROCm execution provider for GPU acceleration" << std::endl;
} catch (const Ort::Exception& e) {
std::cout << "ROCm execution provider not available, falling back to CPU: " << e.what() << std::endl;
}
}
#endif
}

Expand Down Expand Up @@ -203,10 +240,11 @@ void print_model_input_output_info(const Ort::Session& session){
}

Ort::Env create_ORT_env(){
#if ORT_API_VERSION < 24 // Removed in ONNX Runtime 1.24.0
if (Ort::Global<void>::api_ == nullptr){
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Onnx API returned a null pointer.");
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Onnx API returned a null pointer.");
}

#endif
return Ort::Env();
}

Expand Down
Loading