From 8e9188e265622bc811bab735c08135eec6cbd6fc Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Thu, 4 Jan 2024 11:12:48 +1000 Subject: [PATCH] Add SessionOptions use_deterministic_compute to the C and C++ APIs. (#18944) ### Description SessionOptions use_deterministic_compute can be set via the python API. User request to enable setting via C API. ### Motivation and Context #17416 --- .../onnxruntime/core/session/onnxruntime_c_api.h | 15 ++++++++++++++- .../core/session/onnxruntime_cxx_api.h | 1 + .../core/session/onnxruntime_cxx_inline.h | 6 ++++++ onnxruntime/core/session/abi_session_options.cc | 7 +++++++ onnxruntime/core/session/onnxruntime_c_api.cc | 1 + onnxruntime/core/session/ort_apis.h | 1 + .../test/shared_lib/test_session_options.cc | 6 ++++++ 7 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index dbd5ad4125..06fef6bf72 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -29,8 +29,9 @@ */ #pragma once -#include +#include #include +#include #include /** \brief The API version defined in this header @@ -4515,6 +4516,18 @@ struct OrtApi { * \since Version 1.17. */ ORT_API2_STATUS(ReadOpAttr, _In_ const OrtOpAttr* op_attr, _In_ OrtOpAttrType type, _Inout_ void* data, _In_ size_t len, _Out_ size_t* out); + + /** \brief Set whether to use deterministic compute. + * + * Default is false. If set to true, this will enable deterministic compute for GPU kernels where possible. + * Note that this most likely will have a performance cost. + * + * \param[in] options + * \param[in] value + * + * \since Version 1.17. + */ + ORT_API2_STATUS(SetDeterministicCompute, _Inout_ OrtSessionOptions* options, bool value); }; /* diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_api.h b/include/onnxruntime/core/session/onnxruntime_cxx_api.h index 92c25d8688..16d9451624 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_api.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_api.h @@ -845,6 +845,7 @@ struct SessionOptionsImpl : ConstSessionOptionsImpl { SessionOptionsImpl& SetIntraOpNumThreads(int intra_op_num_threads); ///< Wraps OrtApi::SetIntraOpNumThreads SessionOptionsImpl& SetInterOpNumThreads(int inter_op_num_threads); ///< Wraps OrtApi::SetInterOpNumThreads SessionOptionsImpl& SetGraphOptimizationLevel(GraphOptimizationLevel graph_optimization_level); ///< Wraps OrtApi::SetSessionGraphOptimizationLevel + SessionOptionsImpl& SetDeterministicCompute(bool value); ///< Wraps OrtApi::SetDeterministicCompute SessionOptionsImpl& EnableCpuMemArena(); ///< Wraps OrtApi::EnableCpuMemArena SessionOptionsImpl& DisableCpuMemArena(); ///< Wraps OrtApi::DisableCpuMemArena diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h index 860a27fc73..63e5560373 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h @@ -656,6 +656,12 @@ inline SessionOptionsImpl& SessionOptionsImpl::SetGraphOptimizationLevel(G return *this; } +template +inline SessionOptionsImpl& SessionOptionsImpl::SetDeterministicCompute(bool value) { + ThrowOnError(GetApi().SetDeterministicCompute(this->p_, value)); + return *this; +} + template inline SessionOptionsImpl& SessionOptionsImpl::SetOptimizedModelFilePath(const ORTCHAR_T* optimized_model_filepath) { ThrowOnError(GetApi().SetOptimizedModelFilePath(this->p_, optimized_model_filepath)); diff --git a/onnxruntime/core/session/abi_session_options.cc b/onnxruntime/core/session/abi_session_options.cc index fb314b161f..e2084e9ef4 100644 --- a/onnxruntime/core/session/abi_session_options.cc +++ b/onnxruntime/core/session/abi_session_options.cc @@ -293,3 +293,10 @@ ORT_API_STATUS_IMPL(OrtApis::AddExternalInitializers, _In_ OrtSessionOptions* op return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, "External initializers are not supported in this build"); #endif } + +ORT_API_STATUS_IMPL(OrtApis::SetDeterministicCompute, _Inout_ OrtSessionOptions* options, bool value) { + API_IMPL_BEGIN + options->value.use_deterministic_compute = value; + return nullptr; + API_IMPL_END +} diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index 9f8786b727..76a8a77802 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -2721,6 +2721,7 @@ static constexpr OrtApi ort_api_1_to_17 = { &OrtApis::ShapeInferContext_SetOutputTypeShape, &OrtApis::SetSymbolicDimensions, &OrtApis::ReadOpAttr, + &OrtApis::SetDeterministicCompute, }; // OrtApiBase can never change as there is no way to know what version of OrtApiBase is returned by OrtGetApiBase. diff --git a/onnxruntime/core/session/ort_apis.h b/onnxruntime/core/session/ort_apis.h index 09c83219ad..c9e4074a1a 100644 --- a/onnxruntime/core/session/ort_apis.h +++ b/onnxruntime/core/session/ort_apis.h @@ -500,5 +500,6 @@ ORT_API_STATUS_IMPL(ShapeInferContext_GetAttribute, _In_ const OrtShapeInferCont ORT_API_STATUS_IMPL(ShapeInferContext_SetOutputTypeShape, _In_ const OrtShapeInferContext* context, _In_ size_t index, _In_ const OrtTensorTypeAndShapeInfo* info); ORT_API_STATUS_IMPL(SetSymbolicDimensions, _In_ OrtTensorTypeAndShapeInfo* info, _In_ const char* dim_params[], _In_ size_t dim_params_length); ORT_API_STATUS_IMPL(ReadOpAttr, _In_ const OrtOpAttr* op_attr, _In_ OrtOpAttrType type, _Inout_ void* data, _In_ size_t len, _Out_ size_t* out); +ORT_API_STATUS_IMPL(SetDeterministicCompute, _Inout_ OrtSessionOptions* options, bool value); } // namespace OrtApis diff --git a/onnxruntime/test/shared_lib/test_session_options.cc b/onnxruntime/test/shared_lib/test_session_options.cc index 64d9803f8b..d706b74f06 100644 --- a/onnxruntime/test/shared_lib/test_session_options.cc +++ b/onnxruntime/test/shared_lib/test_session_options.cc @@ -15,6 +15,12 @@ TEST(CApiTest, session_options_graph_optimization_level) { options.SetGraphOptimizationLevel(ORT_ENABLE_EXTENDED); } +TEST(CApiTest, session_options_deterministic_compute) { + // Manual validation currently. Check that SetDeterministicCompute in abi_session_options.cc is hit. + Ort::SessionOptions options; + options.SetDeterministicCompute(true); +} + #if !defined(ORT_MINIMAL_BUILD) && !defined(ORT_EXTENDED_MINIMAL_BUILD) && !defined(ORT_NO_EXCEPTIONS) TEST(CApiTest, session_options_oversized_affinity_string) {