diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs
index ba774b44e9..5b3c05e9c9 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs
@@ -235,6 +235,11 @@ namespace Microsoft.ML.OnnxRuntime
public IntPtr SetGlobalCustomJoinThreadFn;
public IntPtr SynchronizeBoundInputs;
public IntPtr SynchronizeBoundOutputs;
+ public IntPtr SessionOptionsAppendExecutionProvider_CUDA_V2;
+ public IntPtr CreateCUDAProviderOptions;
+ public IntPtr UpdateCUDAProviderOptions;
+ public IntPtr GetCUDAProviderOptionsAsString;
+ public IntPtr ReleaseCUDAProviderOptions;
}
internal static class NativeMethods
@@ -397,6 +402,15 @@ namespace Microsoft.ML.OnnxRuntime
OrtUpdateTensorRTProviderOptions = (DOrtUpdateTensorRTProviderOptions)Marshal.GetDelegateForFunctionPointer(api_.UpdateTensorRTProviderOptions, typeof(DOrtUpdateTensorRTProviderOptions));
OrtGetTensorRTProviderOptionsAsString = (DOrtGetTensorRTProviderOptionsAsString)Marshal.GetDelegateForFunctionPointer(api_.GetTensorRTProviderOptionsAsString, typeof(DOrtGetTensorRTProviderOptionsAsString));
OrtReleaseTensorRTProviderOptions = (DOrtReleaseTensorRTProviderOptions)Marshal.GetDelegateForFunctionPointer(api_.ReleaseTensorRTProviderOptions, typeof(DOrtReleaseTensorRTProviderOptions));
+
+ SessionOptionsAppendExecutionProvider_CUDA = (DSessionOptionsAppendExecutionProvider_CUDA)Marshal.GetDelegateForFunctionPointer(
+ api_.SessionOptionsAppendExecutionProvider_CUDA, typeof(DSessionOptionsAppendExecutionProvider_CUDA));
+ SessionOptionsAppendExecutionProvider_CUDA_V2 = (DSessionOptionsAppendExecutionProvider_CUDA_V2)Marshal.GetDelegateForFunctionPointer(
+ api_.SessionOptionsAppendExecutionProvider_CUDA_V2, typeof(DSessionOptionsAppendExecutionProvider_CUDA_V2));
+ OrtCreateCUDAProviderOptions = (DOrtCreateCUDAProviderOptions)Marshal.GetDelegateForFunctionPointer(api_.CreateCUDAProviderOptions, typeof(DOrtCreateCUDAProviderOptions));
+ OrtUpdateCUDAProviderOptions = (DOrtUpdateCUDAProviderOptions)Marshal.GetDelegateForFunctionPointer(api_.UpdateCUDAProviderOptions, typeof(DOrtUpdateCUDAProviderOptions));
+ OrtGetCUDAProviderOptionsAsString = (DOrtGetCUDAProviderOptionsAsString)Marshal.GetDelegateForFunctionPointer(api_.GetCUDAProviderOptionsAsString, typeof(DOrtGetCUDAProviderOptionsAsString));
+ OrtReleaseCUDAProviderOptions = (DOrtReleaseCUDAProviderOptions)Marshal.GetDelegateForFunctionPointer(api_.ReleaseCUDAProviderOptions, typeof(DOrtReleaseCUDAProviderOptions));
}
[DllImport(NativeLib.DllName, CharSet = CharSet.Ansi)]
@@ -469,6 +483,49 @@ namespace Microsoft.ML.OnnxRuntime
public delegate void DOrtReleaseTensorRTProviderOptions(IntPtr /*(OrtTensorRTProviderOptions*)*/ trtProviderOptionsInstance);
public static DOrtReleaseTensorRTProviderOptions OrtReleaseTensorRTProviderOptions;
+ ///
+ /// Creates native OrtCUDAProviderOptions instance
+ ///
+ /// (output) native instance of OrtCUDAProviderOptions
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+ public delegate IntPtr /* OrtStatus* */DOrtCreateCUDAProviderOptions(
+ out IntPtr /*(OrtCUDAProviderOptions**)*/ cudaProviderOptionsInstance);
+ public static DOrtCreateCUDAProviderOptions OrtCreateCUDAProviderOptions;
+
+ ///
+ /// Updates native OrtCUDAProviderOptions instance using given key/value pairs
+ ///
+ /// native instance of OrtCUDAProviderOptions
+ /// configuration keys of OrtCUDAProviderOptions
+ /// configuration values of OrtCUDAProviderOptions
+ /// number of configuration keys
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+ public delegate IntPtr /* OrtStatus* */DOrtUpdateCUDAProviderOptions(
+ IntPtr /*(OrtCUDAProviderOptions*)*/ cudaProviderOptionsInstance,
+ IntPtr[] /*(const char* const *)*/ providerOptionsKeys,
+ IntPtr[] /*(const char* const *)*/ providerOptionsValues,
+ UIntPtr /*(size_t)*/ numKeys);
+ public static DOrtUpdateCUDAProviderOptions OrtUpdateCUDAProviderOptions;
+
+ ///
+ /// Get native OrtCUDAProviderOptionsV2 in serialized string
+ ///
+ /// instance of OrtAllocator
+ /// is a UTF-8 null terminated string allocated using 'allocator'
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+ public delegate IntPtr /* OrtStatus* */DOrtGetCUDAProviderOptionsAsString(
+ IntPtr /*(OrtCUDAProviderOptionsV2**)*/ cudaProviderOptionsInstance,
+ IntPtr /*(OrtAllocator*)*/ allocator,
+ out IntPtr /*(char**)*/ptr);
+ public static DOrtGetCUDAProviderOptionsAsString OrtGetCUDAProviderOptionsAsString;
+
+ ///
+ /// Releases native OrtCUDAProviderOptions instance
+ ///
+ /// native instance of OrtCUDAProviderOptions to be released
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+ public delegate void DOrtReleaseCUDAProviderOptions(IntPtr /*(OrtCUDAProviderOptions*)*/ cudaProviderOptionsInstance);
+ public static DOrtReleaseCUDAProviderOptions OrtReleaseCUDAProviderOptions;
#endregion
#region Status API
@@ -820,6 +877,30 @@ namespace Microsoft.ML.OnnxRuntime
public static DSessionOptionsAppendExecutionProvider_TensorRT_V2 SessionOptionsAppendExecutionProvider_TensorRT_V2;
+ ///
+ /// Append a CUDA EP instance (configured based on given provider options) to the native OrtSessionOptions instance
+ ///
+ /// Native OrtSessionOptions instance
+ /// Native OrtCUDAProviderOptions instance
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+ public delegate IntPtr /*(OrtStatus*)*/DSessionOptionsAppendExecutionProvider_CUDA(
+ IntPtr /*(OrtSessionOptions*)*/ options,
+ IntPtr /*(const OrtCUDAProviderOptions*)*/ cudaProviderOptions);
+
+ public static DSessionOptionsAppendExecutionProvider_CUDA SessionOptionsAppendExecutionProvider_CUDA;
+
+ ///
+ /// Append a CUDA EP instance (configured based on given provider options) to the native OrtSessionOptions instance
+ ///
+ /// Native OrtSessionOptions instance
+ /// Native OrtCUDAProviderOptionsV2 instance
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+ public delegate IntPtr /*(OrtStatus*)*/DSessionOptionsAppendExecutionProvider_CUDA_V2(
+ IntPtr /*(OrtSessionOptions*)*/ options,
+ IntPtr /*(const OrtCUDAProviderOptionsV2*)*/ cudaProviderOptions);
+
+ public static DSessionOptionsAppendExecutionProvider_CUDA_V2 SessionOptionsAppendExecutionProvider_CUDA_V2;
+
///
/// Free Dimension override (by denotation)
///
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs
index c9e3071e84..5e6f1b8ec3 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs
@@ -120,6 +120,104 @@ namespace Microsoft.ML.OnnxRuntime
#endregion
}
+
+ ///
+ /// Holds the options for configuring a CUDA Execution Provider instance
+ ///
+ public class OrtCUDAProviderOptions : SafeHandle
+ {
+ internal IntPtr Handle
+ {
+ get
+ {
+ return handle;
+ }
+ }
+
+
+ #region Constructor
+
+ ///
+ /// Constructs an empty OrtCUDAroviderOptions instance
+ ///
+ public OrtCUDAProviderOptions() : base(IntPtr.Zero, true)
+ {
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateCUDAProviderOptions(out handle));
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Get CUDA EP provider options
+ ///
+ /// return C# UTF-16 encoded string
+ public string GetOptions()
+ {
+ var allocator = OrtAllocator.DefaultInstance;
+
+ // Process provider options string
+ IntPtr providerOptions = IntPtr.Zero;
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtGetCUDAProviderOptionsAsString(handle, allocator.Pointer, out providerOptions));
+ using (var ortAllocation = new OrtMemoryAllocation(allocator, providerOptions, 0))
+ {
+ return NativeOnnxValueHelper.StringFromNativeUtf8(providerOptions);
+ }
+ }
+
+ ///
+ /// Updates the configuration knobs of OrtCUDAProviderOptions that will eventually be used to configure a CUDA EP
+ /// Please refer to the following on different key/value pairs to configure a CUDA EP and their meaning:
+ /// https://www.onnxruntime.ai/docs/reference/execution-providers/CUDA-ExecutionProvider.html
+ ///
+ /// key/value pairs used to configure a CUDA Execution Provider
+ public void UpdateOptions(Dictionary providerOptions)
+ {
+
+ using (var cleanupList = new DisposableList())
+ {
+ var keysArray = NativeOnnxValueHelper.ConvertNamesToUtf8(providerOptions.Keys.ToArray(), n => n, cleanupList);
+ var valuesArray = NativeOnnxValueHelper.ConvertNamesToUtf8(providerOptions.Values.ToArray(), n => n, cleanupList);
+
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtUpdateCUDAProviderOptions(handle, keysArray, valuesArray, (UIntPtr)providerOptions.Count));
+ }
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ ///
+ /// Overrides SafeHandle.IsInvalid
+ ///
+ /// returns true if handle is equal to Zero
+ public override bool IsInvalid { get { return handle == IntPtr.Zero; } }
+
+ #endregion
+
+ #region Private Methods
+
+
+ #endregion
+
+ #region SafeHandle
+ ///
+ /// Overrides SafeHandle.ReleaseHandle() to properly dispose of
+ /// the native instance of OrtCUDAProviderOptions
+ ///
+ /// always returns true
+ protected override bool ReleaseHandle()
+ {
+ NativeMethods.OrtReleaseCUDAProviderOptions(handle);
+ handle = IntPtr.Zero;
+ return true;
+ }
+
+ #endregion
+ }
+
+
///
/// This helper class contains methods to handle values of provider options
///
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs
index ef7140a3ec..34db0bd12f 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs
@@ -66,6 +66,28 @@ namespace Microsoft.ML.OnnxRuntime
return options;
}
+ ///
+ /// A helper method to construct a SessionOptions object for CUDA execution provider.
+ /// Use only if CUDA is installed and you have the onnxruntime package specific to this Execution Provider.
+ ///
+ /// CUDA EP provider options
+ /// A SessionsOptions() object configured for execution on provider options
+ public static SessionOptions MakeSessionOptionWithCudaProvider(OrtCUDAProviderOptions cudaProviderOptions)
+ {
+ CheckCudaExecutionProviderDLLs();
+ SessionOptions options = new SessionOptions();
+ try
+ {
+ options.AppendExecutionProvider_CUDA(cudaProviderOptions);
+ return options;
+ }
+ catch (Exception)
+ {
+ options.Dispose();
+ throw;
+ }
+ }
+
///
/// A helper method to construct a SessionOptions object for TensorRT execution.
/// Use only if CUDA/TensorRT are installed and you have the onnxruntime package specific to this Execution Provider.
@@ -191,6 +213,20 @@ namespace Microsoft.ML.OnnxRuntime
#endif
}
+ ///
+ /// Append a CUDA EP instance (based on specified configuration) to the SessionOptions instance.
+ /// Use only if you have the onnxruntime package specific to this Execution Provider.
+ ///
+ /// CUDA EP provider options
+ public void AppendExecutionProvider_CUDA(OrtCUDAProviderOptions cudaProviderOptions)
+ {
+#if __MOBILE__
+ throw new NotSupportedException("The CUDA Execution Provider is not supported in this build");
+#else
+ NativeApiStatus.VerifySuccess(NativeMethods.SessionOptionsAppendExecutionProvider_CUDA_V2(handle, cudaProviderOptions.Handle));
+#endif
+ }
+
///
/// Use only if you have the onnxruntime package specific to this Execution Provider.
///
@@ -245,7 +281,7 @@ namespace Microsoft.ML.OnnxRuntime
#if __MOBILE__
throw new NotSupportedException("The TensorRT Execution Provider is not supported in this build");
#else
- NativeApiStatus.VerifySuccess(NativeMethods.SessionOptionsAppendExecutionProvider_TensorRT(handle, trtProviderOptions.Handle));
+ NativeApiStatus.VerifySuccess(NativeMethods.SessionOptionsAppendExecutionProvider_TensorRT_V2(handle, trtProviderOptions.Handle));
#endif
}
diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs
index 6e3c9c5f89..139d588f27 100644
--- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs
+++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs
@@ -46,6 +46,68 @@ namespace Microsoft.ML.OnnxRuntime.Tests
}
}
+#if USE_CUDA
+
+ [Fact(DisplayName = "TestCUDAProviderOptions")]
+ private void TestCUDAProviderOptions()
+ {
+ string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "squeezenet.onnx");
+
+ using (var cleanUp = new DisposableListTest())
+ {
+ var cudaProviderOptions = new OrtCUDAProviderOptions();
+ cleanUp.Add(cudaProviderOptions);
+
+ var providerOptionsDict = new Dictionary();
+ providerOptionsDict["device_id"] = "0";
+ providerOptionsDict["gpu_mem_limit"] = "20971520";
+ providerOptionsDict["arena_extend_strategy"] = "kSameAsRequested";
+ providerOptionsDict["cudnn_conv_algo_search"] = "DEFAULT";
+ providerOptionsDict["do_copy_in_default_stream"] = "1";
+ providerOptionsDict["cudnn_conv_use_max_workspace"] = "1";
+ cudaProviderOptions.UpdateOptions(providerOptionsDict);
+
+ var resultProviderOptionsDict = new Dictionary();
+ ProviderOptionsValueHelper.StringToDict(cudaProviderOptions.GetOptions(), resultProviderOptionsDict);
+
+ // test provider options configuration
+ string value;
+ value = resultProviderOptionsDict["device_id"];
+ Assert.Equal("0", value);
+ value = resultProviderOptionsDict["gpu_mem_limit"];
+ Assert.Equal("20971520", value);
+ value = resultProviderOptionsDict["arena_extend_strategy"];
+ Assert.Equal("kSameAsRequested", value);
+ value = resultProviderOptionsDict["cudnn_conv_algo_search"];
+ Assert.Equal("DEFAULT", value);
+ value = resultProviderOptionsDict["do_copy_in_default_stream"];
+ Assert.Equal("1", value);
+ value = resultProviderOptionsDict["cudnn_conv_use_max_workspace"];
+ Assert.Equal("1", value);
+
+ // test correctness of provider options
+ SessionOptions options = SessionOptions.MakeSessionOptionWithCudaProvider(cudaProviderOptions);
+ cleanUp.Add(options);
+
+ var session = new InferenceSession(modelPath, options);
+ cleanUp.Add(session);
+
+ var inputMeta = session.InputMetadata;
+ var container = new List();
+ float[] inputData = TestDataLoader.LoadTensorFromFile(@"bench.in"); // this is the data for only one input tensor for this model
+ foreach (var name in inputMeta.Keys)
+ {
+ Assert.Equal(typeof(float), inputMeta[name].ElementType);
+ Assert.True(inputMeta[name].IsTensor);
+ var tensor = new DenseTensor(inputData, inputMeta[name].Dimensions);
+ container.Add(NamedOnnxValue.CreateFromTensor(name, tensor));
+ }
+
+ session.Run(container);
+ }
+ }
+#endif
+
#if USE_TENSORRT
[Fact(DisplayName = "CanRunInferenceOnAModelWithTensorRT")]
private void CanRunInferenceOnAModelWithTensorRT()
diff --git a/include/onnxruntime/core/common/string_helper.h b/include/onnxruntime/core/common/string_helper.h
index 09f153ff1e..ea6ff75f64 100644
--- a/include/onnxruntime/core/common/string_helper.h
+++ b/include/onnxruntime/core/common/string_helper.h
@@ -6,7 +6,7 @@
#include "core/session/onnxruntime_c_api.h"
namespace onnxruntime {
-#ifdef USE_TENSORRT
+#if defined(USE_TENSORRT) || defined(USE_CUDA)
static char* StrDup(const std::string& str, _Inout_ OrtAllocator* allocator) {
char* output_string = reinterpret_cast(allocator->Alloc(allocator, str.size() + 1));
memcpy(output_string, str.c_str(), str.size());
diff --git a/include/onnxruntime/core/providers/cuda/cuda_provider_options.h b/include/onnxruntime/core/providers/cuda/cuda_provider_options.h
new file mode 100644
index 0000000000..4c931e2ec4
--- /dev/null
+++ b/include/onnxruntime/core/providers/cuda/cuda_provider_options.h
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include "onnxruntime_c_api.h"
+#include "core/framework/arena_extend_strategy.h"
+
+///
+/// Options for the CUDA provider that are passed to SessionOptionsAppendExecutionProvider_CUDA_V2.
+/// Please note that this struct is *similar* to OrtCUDAProviderOptions but only to be used internally.
+/// Going forward, new cuda provider options are to be supported via this struct and usage of the publicly defined
+/// OrtCUDAProviderOptions will be deprecated over time.
+/// User can only get the instance of OrtCUDAProviderOptionsV2 via CreateCUDAProviderOptions.
+///
+struct OrtCUDAProviderOptionsV2 {
+ int device_id; // cuda device id.
+ int has_user_compute_stream; // indicator of user specified CUDA compute stream.
+ void* user_compute_stream; // user specified CUDA compute stream.
+ int do_copy_in_default_stream; // flag specifying if the default stream is to be used for copying.
+ OrtCudnnConvAlgoSearch cudnn_conv_algo_search; // cudnn algo search enum.
+ size_t gpu_mem_limit; // BFC Arena memory limit for CUDA.
+ // (will be overridden by contents of `default_memory_arena_cfg` is it exists)
+ onnxruntime::ArenaExtendStrategy arena_extend_strategy; // BFC Arena extension strategy.
+ // (will be overridden by contents of `default_memory_arena_cfg` is it exists)
+ OrtArenaCfg* default_memory_arena_cfg; // BFC Arena config flags.
+ int cudnn_conv_use_max_workspace; // flag specifying if maximum workspace can be used in cudnn conv algo search.
+};
diff --git a/include/onnxruntime/core/platform/tensorrt_provider_options.h b/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h
similarity index 94%
rename from include/onnxruntime/core/platform/tensorrt_provider_options.h
rename to include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h
index 9f5f0ba546..43b0b938f1 100644
--- a/include/onnxruntime/core/platform/tensorrt_provider_options.h
+++ b/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h
@@ -5,8 +5,8 @@
///
/// Options for the TensorRT provider that are passed to SessionOptionsAppendExecutionProvider_TensorRT_V2.
-/// Please note that this sturct is identical to OrtTensorRTProviderOptions but only to be used internally.
-// User can only get the instance of OrtTensorRTProviderOptionsV2 via CreateTensorRTProviderOptions.
+/// Please note that this struct is identical to OrtTensorRTProviderOptions but only to be used internally.
+/// User can only get the instance of OrtTensorRTProviderOptionsV2 via CreateTensorRTProviderOptions.
///
struct OrtTensorRTProviderOptionsV2 {
int device_id; // cuda device id.
diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h
index 8c32416061..92f27b685a 100644
--- a/include/onnxruntime/core/session/onnxruntime_c_api.h
+++ b/include/onnxruntime/core/session/onnxruntime_c_api.h
@@ -30,7 +30,7 @@
*
* This value is used by some API functions to behave as this version of the header expects.
*/
-#define ORT_API_VERSION 10
+#define ORT_API_VERSION 11
#ifdef __cplusplus
extern "C" {
@@ -256,6 +256,7 @@ ORT_RUNTIME_CLASS(ThreadingOptions);
ORT_RUNTIME_CLASS(ArenaCfg);
ORT_RUNTIME_CLASS(PrepackedWeightsContainer);
ORT_RUNTIME_CLASS(TensorRTProviderOptionsV2);
+ORT_RUNTIME_CLASS(CUDAProviderOptionsV2);
#ifdef _WIN32
typedef _Return_type_success_(return == 0) OrtStatus* OrtStatusPtr;
@@ -536,7 +537,7 @@ ORT_EXPORT const OrtApiBase* ORT_API_CALL OrtGetApiBase(void) NO_EXCEPTION;
*/
typedef void (*OrtThreadWorkerFn)(void* ort_worker_fn_param);
-typedef const struct OrtCustomHandleType{ char __place_holder; }* OrtCustomThreadHandle;
+typedef const struct OrtCustomHandleType { char __place_holder; } * OrtCustomThreadHandle;
/** \brief Ort custom thread creation function
*
@@ -3185,6 +3186,81 @@ struct OrtApi {
* \snippet{doc} snippets.dox OrtStatus Return Value
*/
ORT_API2_STATUS(SynchronizeBoundOutputs, _Inout_ OrtIoBinding* binding_ptr);
+
+ /// \name OrtSessionOptions
+ /// @{
+
+ /** \brief Append CUDA execution provider to the session options
+ *
+ * If CUDA is not available (due to a non CUDA enabled build), this function will return failure.
+ *
+ * This is slightly different from OrtApi::SessionOptionsAppendExecutionProvider_CUDA, it takes an
+ * ::OrtCUDAProviderOptions which is publicly defined. This takes an opaque ::OrtCUDAProviderOptionsV2
+ * which must be created with OrtApi::CreateCUDAProviderOptions.
+ *
+ * For OrtApi::SessionOptionsAppendExecutionProvider_CUDA, the user needs to instantiate ::OrtCUDAProviderOptions
+ * as well as allocate/release buffers for some members of ::OrtCUDAProviderOptions.
+ * Here, OrtApi::CreateCUDAProviderOptions and Ortapi::ReleaseCUDAProviderOptions will do the memory management for you.
+ *
+ * \param[in] options
+ * \param[in] cuda_options
+ *
+ * \snippet{doc} snippets.dox OrtStatus Return Value
+ */
+ ORT_API2_STATUS(SessionOptionsAppendExecutionProvider_CUDA_V2,
+ _In_ OrtSessionOptions* options, _In_ const OrtCUDAProviderOptionsV2* cuda_options);
+
+ /// @}
+ /// \name OrtCUDAProviderOptionsV2
+ /// @{
+
+ /** \brief Create an OrtCUDAProviderOptionsV2
+ *
+ * \param[out] out Newly created ::OrtCUDAProviderOptionsV2. Must be released with OrtApi::ReleaseCudaProviderOptions
+ *
+ * \snippet{doc} snippets.dox OrtStatus Return Value
+ */
+ ORT_API2_STATUS(CreateCUDAProviderOptions, _Outptr_ OrtCUDAProviderOptionsV2** out);
+
+ /** \brief Set options in a CUDA Execution Provider.
+ *
+ * Please refer to https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html#configuration-options
+ * to know the available keys and values. Key should be in null terminated string format of the member of ::OrtCUDAProviderOptionsV2
+ * and value should be its related range.
+ *
+ * For example, key="device_id" and value="0"
+ *
+ * \param[in] cuda_options
+ * \param[in] provider_options_keys Array of UTF-8 null-terminated string for provider options keys
+ * \param[in] provider_options_values Array of UTF-8 null-terminated string for provider options values
+ * \param[in] num_keys Number of elements in the `provider_option_keys` and `provider_options_values` arrays
+ *
+ * \snippet{doc} snippets.dox OrtStatus Return Value
+ */
+ ORT_API2_STATUS(UpdateCUDAProviderOptions, _Inout_ OrtCUDAProviderOptionsV2* cuda_options,
+ _In_reads_(num_keys) const char* const* provider_options_keys,
+ _In_reads_(num_keys) const char* const* provider_options_values,
+ _In_ size_t num_keys);
+
+ /**
+ * Get serialized CUDA provider options string.
+ *
+ * For example, "device_id=0;arena_extend_strategy=0;......"
+ *
+ * \param cuda_options - OrtCUDAProviderOptionsV2 instance
+ * \param allocator - a ptr to an instance of OrtAllocator obtained with CreateAllocator() or GetAllocatorWithDefaultOptions()
+ * the specified allocator will be used to allocate continuous buffers for output strings and lengths.
+ * \param ptr - is a UTF-8 null terminated string allocated using 'allocator'. The caller is responsible for using the same allocator to free it.
+ */
+ ORT_API2_STATUS(GetCUDAProviderOptionsAsString, _In_ const OrtCUDAProviderOptionsV2* cuda_options, _Inout_ OrtAllocator* allocator, _Outptr_ char** ptr);
+
+ /** \brief Release an ::OrtCUDAProviderOptionsV2
+ *
+ * \note This is an exception in the naming convention of other Release* functions, as the name of the method does not have the V2 suffix, but the type does
+ */
+ void(ORT_API_CALL* ReleaseCUDAProviderOptions)(_Frees_ptr_opt_ OrtCUDAProviderOptionsV2* input);
+
+ /// @}
};
/*
diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider_info.cc b/onnxruntime/core/providers/cuda/cuda_execution_provider_info.cc
index 2214f0840f..5a043b86a1 100644
--- a/onnxruntime/core/providers/cuda/cuda_execution_provider_info.cc
+++ b/onnxruntime/core/providers/cuda/cuda_execution_provider_info.cc
@@ -3,6 +3,7 @@
#include "core/providers/shared_library/provider_api.h"
#include "core/providers/cuda/cuda_execution_provider_info.h"
+#include "core/providers/cuda/cuda_provider_options.h"
#include "core/common/make_string.h"
#include "core/common/parse_string.h"
@@ -116,4 +117,17 @@ ProviderOptions CUDAExecutionProviderInfo::ToProviderOptions(const CUDAExecution
return options;
}
+ProviderOptions CUDAExecutionProviderInfo::ToProviderOptions(const OrtCUDAProviderOptionsV2& info) {
+ const ProviderOptions options{
+ {cuda::provider_option_names::kDeviceId, MakeStringWithClassicLocale(info.device_id)},
+ {cuda::provider_option_names::kMemLimit, MakeStringWithClassicLocale(info.gpu_mem_limit)},
+ {cuda::provider_option_names::kArenaExtendStrategy, EnumToName(*arena_extend_strategy_mapping, info.arena_extend_strategy)},
+ {cuda::provider_option_names::kCudnnConvAlgoSearch, EnumToName(*ort_cudnn_conv_algo_search_mapping, info.cudnn_conv_algo_search)},
+ {cuda::provider_option_names::kDoCopyInDefaultStream, MakeStringWithClassicLocale(info.do_copy_in_default_stream)},
+ {cuda::provider_option_names::kCudnnConvUseMaxWorkspace, MakeStringWithClassicLocale(info.cudnn_conv_use_max_workspace)},
+ };
+
+ return options;
+}
+
} // namespace onnxruntime
diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider_info.h b/onnxruntime/core/providers/cuda/cuda_execution_provider_info.h
index 5240f818a3..7bd0a416d6 100644
--- a/onnxruntime/core/providers/cuda/cuda_execution_provider_info.h
+++ b/onnxruntime/core/providers/cuda/cuda_execution_provider_info.h
@@ -54,5 +54,6 @@ struct CUDAExecutionProviderInfo {
static CUDAExecutionProviderInfo FromProviderOptions(const ProviderOptions& options);
static ProviderOptions ToProviderOptions(const CUDAExecutionProviderInfo& info);
+ static ProviderOptions ToProviderOptions(const OrtCUDAProviderOptionsV2& info);
};
} // namespace onnxruntime
diff --git a/onnxruntime/core/providers/cuda/cuda_provider_factory.cc b/onnxruntime/core/providers/cuda/cuda_provider_factory.cc
index 45e10fa14c..95eda3d4f4 100644
--- a/onnxruntime/core/providers/cuda/cuda_provider_factory.cc
+++ b/onnxruntime/core/providers/cuda/cuda_provider_factory.cc
@@ -4,6 +4,7 @@
#include "core/providers/shared_library/provider_api.h"
#include "core/providers/cuda/cuda_provider_factory_creator.h"
#include "core/providers/cuda/cuda_provider_factory.h"
+#include "core/providers/cuda/cuda_provider_options.h"
#include
@@ -186,21 +187,42 @@ struct CUDA_Provider : Provider {
void* GetInfo() override { return &g_info; }
std::shared_ptr CreateExecutionProviderFactory(const void* void_params) override {
- auto params = reinterpret_cast(void_params);
+ auto params = reinterpret_cast(void_params);
CUDAExecutionProviderInfo info{};
info.device_id = gsl::narrow(params->device_id);
info.gpu_mem_limit = params->gpu_mem_limit;
- info.arena_extend_strategy = static_cast(params->arena_extend_strategy);
+ info.arena_extend_strategy = params->arena_extend_strategy;
info.cudnn_conv_algo_search = params->cudnn_conv_algo_search;
info.do_copy_in_default_stream = params->do_copy_in_default_stream != 0;
info.has_user_compute_stream = params->has_user_compute_stream != 0;
info.user_compute_stream = params->user_compute_stream;
info.default_memory_arena_cfg = params->default_memory_arena_cfg;
+ info.cudnn_conv_use_max_workspace = params->cudnn_conv_use_max_workspace != 0;
return std::make_shared(info);
}
+ void UpdateProviderOptions(void* provider_options, const ProviderOptions& options) override {
+ auto internal_options = onnxruntime::CUDAExecutionProviderInfo::FromProviderOptions(options);
+ auto& cuda_options = *reinterpret_cast(provider_options);
+
+ cuda_options.device_id = internal_options.device_id;
+ cuda_options.cudnn_conv_algo_search = internal_options.cudnn_conv_algo_search;
+ cuda_options.gpu_mem_limit = internal_options.gpu_mem_limit;
+ cuda_options.arena_extend_strategy = internal_options.arena_extend_strategy;
+ cuda_options.do_copy_in_default_stream = internal_options.do_copy_in_default_stream;
+ cuda_options.has_user_compute_stream = internal_options.has_user_compute_stream;
+ cuda_options.user_compute_stream = internal_options.user_compute_stream;
+ cuda_options.default_memory_arena_cfg = internal_options.default_memory_arena_cfg;
+ cuda_options.cudnn_conv_use_max_workspace = internal_options.cudnn_conv_use_max_workspace;
+ }
+
+ ProviderOptions GetProviderOptions(const void* provider_options) override {
+ auto& options = *reinterpret_cast(provider_options);
+ return onnxruntime::CUDAExecutionProviderInfo::ToProviderOptions(options);
+ }
+
void Shutdown() override {
Shutdown_DeleteRegistry();
}
diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc
index 086c7236f3..b954b78870 100644
--- a/onnxruntime/core/session/onnxruntime_c_api.cc
+++ b/onnxruntime/core/session/onnxruntime_c_api.cc
@@ -2271,7 +2271,7 @@ Second example, if we wanted to add and remove some members, we'd do this:
In GetApi we now make it return ort_api_3 for version 3.
*/
-static constexpr OrtApi ort_api_1_to_10 = {
+static constexpr OrtApi ort_api_1_to_11 = {
// NOTE: The ordering of these fields MUST not change after that version has shipped since existing binaries depend on this ordering.
// Shipped as version 1 - DO NOT MODIFY (see above text for more information)
@@ -2511,10 +2511,15 @@ static constexpr OrtApi ort_api_1_to_10 = {
&OrtApis::SetGlobalCustomThreadCreationOptions,
&OrtApis::SetGlobalCustomJoinThreadFn,
&OrtApis::SynchronizeBoundInputs,
- &OrtApis::SynchronizeBoundOutputs
+ &OrtApis::SynchronizeBoundOutputs,
// End of Version 10 - DO NOT MODIFY ABOVE (see above text for more information)
// Version 11 - In development, feel free to add/remove/rearrange here
+ &OrtApis::SessionOptionsAppendExecutionProvider_CUDA_V2,
+ &OrtApis::CreateCUDAProviderOptions,
+ &OrtApis::UpdateCUDAProviderOptions,
+ &OrtApis::GetCUDAProviderOptionsAsString,
+ &OrtApis::ReleaseCUDAProviderOptions,
};
// Asserts to do a some checks to ensure older Versions of the OrtApi never change (will detect an addition or deletion but not if they cancel out each other)
@@ -2527,17 +2532,19 @@ static_assert(offsetof(OrtApi, SetGlobalSpinControl) / sizeof(void*) == 149, "Si
static_assert(offsetof(OrtApi, ReleaseArenaCfg) / sizeof(void*) == 157, "Size of version 6 API cannot change");
static_assert(offsetof(OrtApi, GetCurrentGpuDeviceId) / sizeof(void*) == 161, "Size of version 7 API cannot change");
static_assert(offsetof(OrtApi, CreateSessionFromArrayWithPrepackedWeightsContainer) / sizeof(void*) == 169, "Size of version 8 API cannot change");
+static_assert(offsetof(OrtApi, GetSparseTensorIndices) / sizeof(void*) == 191, "Size of version 9 API cannot change");
+static_assert(offsetof(OrtApi, SynchronizeBoundOutputs) / sizeof(void*) == 203, "Size of version 10 API cannot change");
// So that nobody forgets to finish an API version, this check will serve as a reminder:
static_assert(std::string_view(ORT_VERSION) == "1.11.0", "ORT_Version change detected, please follow below steps to ensure OrtApi is updated properly");
// 1. Update the hardcoded version string in above static_assert to silence it
-// 2. If there were any APIs added to ort_api_1_to_10 above:
+// 2. If there were any APIs added to ort_api_1_to_11 above:
// a. Add the 'End of version #' markers (pattern above should be obvious)
// b. Add a static_assert in the directly above list of version sizes to ensure nobody adds any more functions to the just shipped API version
ORT_API(const OrtApi*, OrtApis::GetApi, uint32_t version) {
if (version >= 1 && version <= ORT_API_VERSION)
- return &ort_api_1_to_10;
+ return &ort_api_1_to_11;
fprintf(stderr, "The given version [%u] is not supported, only version 1 to %u is supported in this build.\n",
version, ORT_API_VERSION);
diff --git a/onnxruntime/core/session/ort_apis.h b/onnxruntime/core/session/ort_apis.h
index 2345e00ed3..46aa26030f 100644
--- a/onnxruntime/core/session/ort_apis.h
+++ b/onnxruntime/core/session/ort_apis.h
@@ -327,4 +327,13 @@ ORT_API_STATUS_IMPL(SetGlobalCustomThreadCreationOptions, _Inout_ OrtThreadingOp
ORT_API_STATUS_IMPL(SetGlobalCustomJoinThreadFn, _Inout_ OrtThreadingOptions* tp_options, _In_ OrtCustomJoinThreadFn ort_custom_join_thread_fn);
ORT_API_STATUS_IMPL(SynchronizeBoundInputs, _Inout_ OrtIoBinding* binding_ptr);
ORT_API_STATUS_IMPL(SynchronizeBoundOutputs, _Inout_ OrtIoBinding* binding_ptr);
+ORT_API_STATUS_IMPL(SessionOptionsAppendExecutionProvider_CUDA_V2,
+ _In_ OrtSessionOptions* options, _In_ const OrtCUDAProviderOptionsV2* cuda_options);
+ORT_API_STATUS_IMPL(CreateCUDAProviderOptions, _Outptr_ OrtCUDAProviderOptionsV2** out);
+ORT_API_STATUS_IMPL(UpdateCUDAProviderOptions, _Inout_ OrtCUDAProviderOptionsV2* cuda_options,
+ _In_reads_(num_keys) const char* const* provider_options_keys,
+ _In_reads_(num_keys) const char* const* provider_options_values,
+ size_t num_keys);
+ORT_API_STATUS_IMPL(GetCUDAProviderOptionsAsString, _In_ const OrtCUDAProviderOptionsV2* cuda_options, _Inout_ OrtAllocator* allocator, _Outptr_ char** ptr);
+ORT_API(void, ReleaseCUDAProviderOptions, _Frees_ptr_opt_ OrtCUDAProviderOptionsV2*);
} // namespace OrtApis
diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc
index bec88849df..98d057d57e 100644
--- a/onnxruntime/core/session/provider_bridge_ort.cc
+++ b/onnxruntime/core/session/provider_bridge_ort.cc
@@ -65,9 +65,10 @@ using IndexedSubGraph_MetaDef = IndexedSubGraph::MetaDef;
#include "core/providers/cuda/cuda_provider_factory.h"
#include "core/providers/rocm/rocm_provider_factory.h"
#include "core/providers/dnnl/dnnl_provider_factory.h"
-#include "core/providers/tensorrt/tensorrt_provider_factory.h"
#include "core/providers/openvino/openvino_provider_factory.h"
-#include "core/platform/tensorrt_provider_options.h"
+#include "core/providers/tensorrt/tensorrt_provider_factory.h"
+#include "core/providers/tensorrt/tensorrt_provider_options.h"
+#include "core/providers/cuda/cuda_provider_options.h"
// The filename extension for a shared library is different per platform
#ifdef _WIN32
@@ -1076,7 +1077,33 @@ std::unique_ptr CreateROCMPinnedAllocator(int16_t device_id, const c
return nullptr;
}
+// Adapter to convert the legacy OrtCUDAProviderOptions to the latest OrtCUDAProviderOptionsV2
+OrtCUDAProviderOptionsV2 OrtCUDAProviderOptionsToOrtCUDAProviderOptionsV2(const OrtCUDAProviderOptions* legacy_cuda_options) {
+ OrtCUDAProviderOptionsV2 cuda_options_converted;
+
+ cuda_options_converted.device_id = legacy_cuda_options->device_id;
+ cuda_options_converted.cudnn_conv_algo_search = legacy_cuda_options->cudnn_conv_algo_search;
+ cuda_options_converted.gpu_mem_limit = legacy_cuda_options->gpu_mem_limit;
+ cuda_options_converted.arena_extend_strategy = static_cast(legacy_cuda_options->arena_extend_strategy);
+ cuda_options_converted.do_copy_in_default_stream = legacy_cuda_options->do_copy_in_default_stream;
+ cuda_options_converted.has_user_compute_stream = legacy_cuda_options->has_user_compute_stream;
+ cuda_options_converted.user_compute_stream = legacy_cuda_options->user_compute_stream;
+ cuda_options_converted.default_memory_arena_cfg = legacy_cuda_options->default_memory_arena_cfg;
+ // Use default value as this field is not available in OrtCUDAProviderOptions
+ cuda_options_converted.cudnn_conv_use_max_workspace = 0;
+
+ return cuda_options_converted;
+}
+
std::shared_ptr CreateExecutionProviderFactory_Cuda(const OrtCUDAProviderOptions* provider_options) {
+ OrtCUDAProviderOptionsV2 cuda_options_converted = onnxruntime::OrtCUDAProviderOptionsToOrtCUDAProviderOptionsV2(provider_options);
+ if (auto* provider = s_library_cuda.Get())
+ return provider->CreateExecutionProviderFactory(&cuda_options_converted);
+
+ return nullptr;
+}
+
+std::shared_ptr CreateExecutionProviderFactory_Cuda(const OrtCUDAProviderOptionsV2* provider_options) {
if (auto* provider = s_library_cuda.Get())
return provider->CreateExecutionProviderFactory(provider_options);
@@ -1215,6 +1242,20 @@ ProviderOptions GetProviderInfo_Tensorrt(const OrtTensorRTProviderOptions* provi
return {};
}
+void UpdateProviderInfo_Cuda(OrtCUDAProviderOptionsV2* provider_options, const ProviderOptions& options) {
+ if (auto provider = s_library_cuda.Get()) {
+ provider->UpdateProviderOptions(reinterpret_cast(provider_options), options);
+ }
+}
+
+ProviderOptions GetProviderInfo_Cuda(const OrtCUDAProviderOptionsV2* provider_options) {
+ if (auto provider = s_library_cuda.Get()) {
+ return provider->GetProviderOptions(reinterpret_cast(provider_options));
+ }
+
+ return {};
+}
+
} // namespace onnxruntime
ORT_API_STATUS_IMPL(OrtSessionOptionsAppendExecutionProvider_Dnnl, _In_ OrtSessionOptions* options, int use_arena) {
@@ -1448,3 +1489,107 @@ ORT_API(void, OrtApis::ReleaseTensorRTProviderOptions, _Frees_ptr_opt_ OrtTensor
ORT_UNUSED_PARAMETER(ptr);
#endif
}
+
+ORT_API_STATUS_IMPL(OrtApis::SessionOptionsAppendExecutionProvider_CUDA_V2, _In_ OrtSessionOptions* options, _In_ const OrtCUDAProviderOptionsV2* cuda_options) {
+ API_IMPL_BEGIN
+ auto factory = onnxruntime::CreateExecutionProviderFactory_Cuda(cuda_options);
+ if (!factory) {
+ return OrtApis::CreateStatus(ORT_FAIL, "OrtSessionOptionsAppendExecutionProvider_Cuda: Failed to load shared library");
+ }
+
+ options->provider_factories.push_back(factory);
+ return nullptr;
+ API_IMPL_END
+}
+
+ORT_API_STATUS_IMPL(OrtApis::CreateCUDAProviderOptions, _Outptr_ OrtCUDAProviderOptionsV2** out) {
+ API_IMPL_BEGIN
+#ifdef USE_CUDA
+ *out = new OrtCUDAProviderOptionsV2();
+ (*out)->device_id = 0;
+ (*out)->cudnn_conv_algo_search = OrtCudnnConvAlgoSearch::OrtCudnnConvAlgoSearchExhaustive;
+ (*out)->gpu_mem_limit = std::numeric_limits::max();
+ (*out)->arena_extend_strategy = static_cast(0);
+ (*out)->do_copy_in_default_stream = 1;
+ (*out)->has_user_compute_stream = 0;
+ (*out)->user_compute_stream = nullptr;
+ (*out)->default_memory_arena_cfg = nullptr;
+ (*out)->cudnn_conv_use_max_workspace = 0;
+ return nullptr;
+#else
+ ORT_UNUSED_PARAMETER(out);
+ return CreateStatus(ORT_FAIL, "CUDA execution provider is not enabled in this build.");
+#endif
+ API_IMPL_END
+}
+
+ORT_API_STATUS_IMPL(OrtApis::UpdateCUDAProviderOptions,
+ _Inout_ OrtCUDAProviderOptionsV2* cuda_options,
+ _In_reads_(num_keys) const char* const* provider_options_keys,
+ _In_reads_(num_keys) const char* const* provider_options_values,
+ size_t num_keys) {
+ API_IMPL_BEGIN
+#ifdef USE_CUDA
+ onnxruntime::ProviderOptions provider_options_map;
+ for (size_t i = 0; i != num_keys; ++i) {
+ if (provider_options_keys[i] == nullptr || provider_options_keys[i][0] == '\0' ||
+ provider_options_values[i] == nullptr || provider_options_values[i][0] == '\0') {
+ return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "key/value cannot be empty");
+ }
+
+ provider_options_map[provider_options_keys[i]] = provider_options_values[i];
+ }
+
+ onnxruntime::UpdateProviderInfo_Cuda(cuda_options,
+ reinterpret_cast(provider_options_map));
+ return nullptr;
+#else
+ ORT_UNUSED_PARAMETER(cuda_options);
+ ORT_UNUSED_PARAMETER(provider_options_keys);
+ ORT_UNUSED_PARAMETER(provider_options_values);
+ ORT_UNUSED_PARAMETER(num_keys);
+ return CreateStatus(ORT_FAIL, "CUDA execution provider is not enabled in this build.");
+#endif
+ API_IMPL_END
+}
+
+ORT_API_STATUS_IMPL(OrtApis::GetCUDAProviderOptionsAsString, _In_ const OrtCUDAProviderOptionsV2* cuda_options, _Inout_ OrtAllocator* allocator,
+ _Outptr_ char** ptr) {
+ API_IMPL_BEGIN
+#ifdef USE_CUDA
+ onnxruntime::ProviderOptions options = onnxruntime::GetProviderInfo_Cuda(cuda_options);
+ onnxruntime::ProviderOptions::iterator it = options.begin();
+ std::string options_str = "";
+
+ while (it != options.end()) {
+ if (options_str == "") {
+ options_str += it->first;
+ options_str += "=";
+ options_str += it->second;
+ } else {
+ options_str += ";";
+ options_str += it->first;
+ options_str += "=";
+ options_str += it->second;
+ }
+ it++;
+ }
+
+ *ptr = onnxruntime::StrDup(options_str, allocator);
+ return nullptr;
+#else
+ ORT_UNUSED_PARAMETER(cuda_options);
+ ORT_UNUSED_PARAMETER(allocator);
+ ORT_UNUSED_PARAMETER(ptr);
+ return CreateStatus(ORT_FAIL, "CUDA execution provider is not enabled in this build.");
+#endif
+ API_IMPL_END
+}
+
+ORT_API(void, OrtApis::ReleaseCUDAProviderOptions, _Frees_ptr_opt_ OrtCUDAProviderOptionsV2* ptr) {
+#ifdef USE_CUDA
+ delete ptr;
+#else
+ ORT_UNUSED_PARAMETER(ptr);
+#endif
+}
diff --git a/onnxruntime/core/session/provider_stubs.cc b/onnxruntime/core/session/provider_stubs.cc
index 2b3369daa8..1db6c5917a 100644
--- a/onnxruntime/core/session/provider_stubs.cc
+++ b/onnxruntime/core/session/provider_stubs.cc
@@ -97,6 +97,42 @@ ORT_API_STATUS_IMPL(OrtApis::SessionOptionsAppendExecutionProvider_CUDA,
return CreateNotEnabledStatus("CUDA");
}
+ORT_API_STATUS_IMPL(OrtApis::SessionOptionsAppendExecutionProvider_CUDA_V2,
+ _In_ OrtSessionOptions* options, _In_ const OrtCUDAProviderOptionsV2* cuda_options) {
+ ORT_UNUSED_PARAMETER(options);
+ ORT_UNUSED_PARAMETER(cuda_options);
+ return CreateNotEnabledStatus("CUDA");
+}
+
+ORT_API_STATUS_IMPL(OrtApis::CreateCUDAProviderOptions, _Outptr_ OrtCUDAProviderOptionsV2** out) {
+ ORT_UNUSED_PARAMETER(out);
+ return CreateNotEnabledStatus("CUDA");
+}
+
+ORT_API_STATUS_IMPL(OrtApis::UpdateCUDAProviderOptions,
+ _Inout_ OrtCUDAProviderOptionsV2* cuda_options,
+ _In_reads_(num_keys) const char* const* provider_options_keys,
+ _In_reads_(num_keys) const char* const* provider_options_values,
+ size_t num_keys) {
+ ORT_UNUSED_PARAMETER(cuda_options);
+ ORT_UNUSED_PARAMETER(provider_options_keys);
+ ORT_UNUSED_PARAMETER(provider_options_values);
+ ORT_UNUSED_PARAMETER(num_keys);
+ return CreateNotEnabledStatus("CUDA");
+}
+
+ORT_API_STATUS_IMPL(OrtApis::GetCUDAProviderOptionsAsString, _In_ const OrtCUDAProviderOptionsV2* cuda_options, _Inout_ OrtAllocator* allocator,
+ _Outptr_ char** ptr) {
+ ORT_UNUSED_PARAMETER(cuda_options);
+ ORT_UNUSED_PARAMETER(allocator);
+ ORT_UNUSED_PARAMETER(ptr);
+ return CreateStatus(ORT_FAIL, "CUDA execution provider is not enabled in this build.");
+}
+
+ORT_API(void, OrtApis::ReleaseCUDAProviderOptions, _Frees_ptr_opt_ OrtCUDAProviderOptionsV2* ptr) {
+ ORT_UNUSED_PARAMETER(ptr);
+}
+
ORT_API_STATUS_IMPL(OrtApis::GetCurrentGpuDeviceId, _In_ int* device_id) {
ORT_UNUSED_PARAMETER(device_id);
return CreateNotEnabledStatus("CUDA");
diff --git a/onnxruntime/test/shared_lib/test_inference.cc b/onnxruntime/test/shared_lib/test_inference.cc
index 4d033432d8..11a8333386 100644
--- a/onnxruntime/test/shared_lib/test_inference.cc
+++ b/onnxruntime/test/shared_lib/test_inference.cc
@@ -1852,6 +1852,51 @@ TEST(CApiTest, TestConfigureTensorRTProviderOptions) {
}
#endif
+#ifdef USE_CUDA
+
+// This test uses CreateCUDAProviderOptions/UpdateCUDAProviderOptions APIs to configure and create a CUDA Execution Provider instance
+TEST(CApiTest, TestConfigureCUDAProviderOptions) {
+ const auto& api = Ort::GetApi();
+
+ OrtCUDAProviderOptionsV2* cuda_options = nullptr;
+ ASSERT_TRUE(api.CreateCUDAProviderOptions(&cuda_options) == nullptr);
+ std::unique_ptr rel_cuda_options(cuda_options, api.ReleaseCUDAProviderOptions);
+
+ std::vector keys{
+ "device_id", "gpu_mem_limit", "arena_extend_strategy",
+ "cudnn_conv_algo_search", "do_copy_in_default_stream", "cudnn_conv_use_max_workspace"};
+
+ std::vector values{
+ "0", "1024", "kSameAsRequested",
+ "DEFAULT", "1", "1"};
+
+ ASSERT_TRUE(api.UpdateCUDAProviderOptions(rel_cuda_options.get(), keys.data(), values.data(), 6) == nullptr);
+
+ OrtAllocator* allocator;
+ ASSERT_TRUE(api.GetAllocatorWithDefaultOptions(&allocator) == nullptr);
+
+ char* cuda_options_str = nullptr;
+ ASSERT_TRUE(api.GetCUDAProviderOptionsAsString(rel_cuda_options.get(), allocator, &cuda_options_str) == nullptr);
+ std::string s(cuda_options_str, strnlen(cuda_options_str, 2048));
+ ASSERT_TRUE(s.find("device_id=0") != std::string::npos);
+ ASSERT_TRUE(s.find("gpu_mem_limit=1024") != std::string::npos);
+ ASSERT_TRUE(s.find("arena_extend_strategy=kSameAsRequested") != std::string::npos);
+ ASSERT_TRUE(s.find("cudnn_conv_algo_search=DEFAULT") != std::string::npos);
+ ASSERT_TRUE(s.find("do_copy_in_default_stream=1") != std::string::npos);
+ ASSERT_TRUE(s.find("cudnn_conv_use_max_workspace=1") != std::string::npos);
+
+ ASSERT_TRUE(api.AllocatorFree(allocator, (void*)cuda_options_str) == nullptr);
+
+ Ort::SessionOptions session_options;
+ ASSERT_TRUE(api.SessionOptionsAppendExecutionProvider_CUDA_V2(static_cast(session_options), rel_cuda_options.get()) == nullptr);
+
+ // if session creation passes, model loads fine
+ std::basic_string model_uri = MODEL_URI;
+ Ort::Session session(*ort_env, model_uri.c_str(), session_options);
+}
+
+#endif
+
namespace TestPerSessionCustomThreadHooks {
std::vector threads;
@@ -1933,4 +1978,3 @@ TEST(CApiTest, crop_and_resize) {
#endif
} // namespace TestPerSessionCustomThreadHooks
-
diff --git a/onnxruntime/test/shared_lib/utils.cc b/onnxruntime/test/shared_lib/utils.cc
index fd2ad701bc..4df1f42a10 100644
--- a/onnxruntime/test/shared_lib/utils.cc
+++ b/onnxruntime/test/shared_lib/utils.cc
@@ -2,11 +2,19 @@
// Licensed under the MIT License.
#include "utils.h"
+#include
OrtCUDAProviderOptions CreateDefaultOrtCudaProviderOptionsWithCustomStream(void* cuda_compute_stream) {
OrtCUDAProviderOptions cuda_options;
+
+ cuda_options.device_id = 0;
+ cuda_options.cudnn_conv_algo_search = OrtCudnnConvAlgoSearch::OrtCudnnConvAlgoSearchExhaustive;
+ cuda_options.gpu_mem_limit = std::numeric_limits::max();
+ cuda_options.arena_extend_strategy = 0;
cuda_options.do_copy_in_default_stream = true;
cuda_options.has_user_compute_stream = cuda_compute_stream != nullptr ? 1 : 0;
cuda_options.user_compute_stream = cuda_compute_stream;
+ cuda_options.default_memory_arena_cfg = nullptr;
+
return cuda_options;
}
diff --git a/onnxruntime/test/util/include/default_providers.h b/onnxruntime/test/util/include/default_providers.h
index 6df390125a..078e135628 100644
--- a/onnxruntime/test/util/include/default_providers.h
+++ b/onnxruntime/test/util/include/default_providers.h
@@ -11,6 +11,7 @@ std::shared_ptr CreateExecutionProviderFactory_ACL(in
std::shared_ptr CreateExecutionProviderFactory_ArmNN(int use_arena);
std::shared_ptr CreateExecutionProviderFactory_CoreML(uint32_t);
std::shared_ptr CreateExecutionProviderFactory_Cuda(const OrtCUDAProviderOptions* provider_options);
+std::shared_ptr CreateExecutionProviderFactory_Cuda(const OrtCUDAProviderOptionsV2* provider_options);
std::shared_ptr CreateExecutionProviderFactory_Dnnl(int use_arena);
std::shared_ptr CreateExecutionProviderFactory_MIGraphX(int device_id);
std::shared_ptr CreateExecutionProviderFactory_Nnapi(