From 157d1844fb241a43def5ed4e97c6a4ba4cb87af0 Mon Sep 17 00:00:00 2001 From: Ori Levari Date: Fri, 13 Nov 2020 21:21:11 -0800 Subject: [PATCH] Named Dimension Override internals test and experimental API (#5805) --- cmake/winml.cmake | 11 +++++++-- cmake/winml_cppwinrt.cmake | 2 +- cmake/winml_unittests.cmake | 1 + .../src/Operators/DmlOperatorReduce.cpp | 2 +- winml/adapter/winml_adapter_apis.h | 1 + winml/adapter/winml_adapter_c_api.cpp | 1 + winml/adapter/winml_adapter_c_api.h | 9 ++++++++ winml/adapter/winml_adapter_session.cpp | 17 ++++++++++++++ ...rosoft.AI.MachineLearning.Experimental.idl | 16 +++++++++++++ winml/dll/module.cpp | 13 ++++++++--- .../LearningModelSessionExperimental.cpp | 18 +++++++++++++++ .../LearningModelSessionExperimental.h | 23 +++++++++++++++++++ ...earningModelSessionOptionsExperimental.cpp | 18 +++++++++++++++ .../LearningModelSessionOptionsExperimental.h | 17 ++++++++++++++ winml/lib/Api.Ort/OnnxruntimeEngine.cpp | 7 ++++++ winml/lib/Api.Ort/OnnxruntimeEngine.h | 3 +++ winml/lib/Common/inc/iengine.h | 3 +++ .../test/api/LearningModelSessionAPITest.cpp | 10 +++++++- winml/test/common/winrt_headers.h | 3 +++ 19 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 winml/lib/Api.Experimental/LearningModelSessionExperimental.cpp create mode 100644 winml/lib/Api.Experimental/LearningModelSessionExperimental.h create mode 100644 winml/lib/Api.Experimental/LearningModelSessionOptionsExperimental.cpp create mode 100644 winml/lib/Api.Experimental/LearningModelSessionOptionsExperimental.h diff --git a/cmake/winml.cmake b/cmake/winml.cmake index ec75d1f4fd..8e1db77834 100644 --- a/cmake/winml.cmake +++ b/cmake/winml.cmake @@ -101,7 +101,7 @@ target_cppwinrt(winml_api_experimental ${winml_midl_defines} # the midl compiler defines ${winml_api_use_ns_prefix} # set ns_prefix ) - +add_dependencies(winml_api_experimental winml_api) target_midl(winml_api_native ${idl_native} # winml native idl to compile @@ -507,6 +507,10 @@ endif(onnxruntime_USE_DML) add_library(winml_lib_api_experimental STATIC ${winml_lib_api_experimental_dir}/Dummy.cpp ${winml_lib_api_experimental_dir}/Dummy.h + ${winml_lib_api_experimental_dir}/LearningModelSessionExperimental.cpp + ${winml_lib_api_experimental_dir}/LearningModelSessionExperimental.h + ${winml_lib_api_experimental_dir}/LearningModelSessionOptionsExperimental.cpp + ${winml_lib_api_experimental_dir}/LearningModelSessionOptionsExperimental.h ) # Compiler options @@ -528,6 +532,7 @@ target_precompiled_header(winml_lib_api_experimental pch.h) # Includes target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api) # windows machine learning generated component headers target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api/comp_generated) # windows machine learning generated component headers +target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api_experimental) # windows machine learning generated component headers target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api_experimental/comp_generated) # windows machine learning generated component headers target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml/sdk/cppwinrt/include) # sdk cppwinrt headers @@ -731,7 +736,9 @@ add_dependencies(winml_dll winml_api_native_internal) target_link_libraries(winml_dll PRIVATE re2) target_link_libraries(winml_dll PRIVATE wil) target_link_libraries(winml_dll PRIVATE winml_lib_api) -target_link_libraries(winml_dll PRIVATE winml_lib_api_experimental) +if (NOT winml_is_inbox) + target_link_libraries(winml_dll PRIVATE winml_lib_api_experimental) +endif() target_link_libraries(winml_dll PRIVATE winml_lib_image) target_link_libraries(winml_dll PRIVATE winml_lib_ort) target_link_libraries(winml_dll PRIVATE winml_lib_telemetry) diff --git a/cmake/winml_cppwinrt.cmake b/cmake/winml_cppwinrt.cmake index 4940d02f0a..68c2f400a4 100644 --- a/cmake/winml_cppwinrt.cmake +++ b/cmake/winml_cppwinrt.cmake @@ -152,7 +152,7 @@ function(target_cppwinrt ${midl_options} ${renamed_idl_fullpath_back_slash} COMMAND - ${cppwinrt_exe} -in ${winmd_filename} -comp ${output_dir_back_slash} -ref ${sdk_metadata_directory} -out ${generated_dir_back_slash} -verbose + ${cppwinrt_exe} -in ${winmd_filename} -comp ${output_dir_back_slash} -ref ${sdk_metadata_directory} -ref ${cmake_current_binary_dir_back_slash} -out ${generated_dir_back_slash} -verbose COMMAND # copy the generated component files into a temporary directory where headers exclusions will be applied xcopy ${output_dir_back_slash} ${temp_dir_back_slash}\\ /Y /D diff --git a/cmake/winml_unittests.cmake b/cmake/winml_unittests.cmake index 76f5aab37f..98d48753ed 100644 --- a/cmake/winml_unittests.cmake +++ b/cmake/winml_unittests.cmake @@ -16,6 +16,7 @@ set(WINML_TEST_INC_DIR ${CMAKE_CURRENT_BINARY_DIR}/winml_api ${CMAKE_CURRENT_BINARY_DIR}/winml_api/comp_generated ${CMAKE_CURRENT_BINARY_DIR}/winml/sdk/cppwinrt/include + ${CMAKE_CURRENT_BINARY_DIR}/winml_api_experimental ${CMAKE_CURRENT_BINARY_DIR}/winml_api_experimental/comp_generated ) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReduce.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReduce.cpp index 72758d743b..47e37e6fb6 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReduce.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReduce.cpp @@ -27,7 +27,7 @@ public: int dimOffset = gsl::narrow_cast(m_inputTensorDescs[0].GetDimensionCount() - reducedDims.size()); for (auto& dim : m_axes) { - assert(dim < reducedDims.size()); // ReduceHelperBase already validated this. + assert(dim < static_cast(reducedDims.size())); // ReduceHelperBase already validated this. reducedDims[dim] = 1; dmlAxes.push_back(static_cast(dim + dimOffset)); } diff --git a/winml/adapter/winml_adapter_apis.h b/winml/adapter/winml_adapter_apis.h index 866a805966..2b3db5ec1f 100644 --- a/winml/adapter/winml_adapter_apis.h +++ b/winml/adapter/winml_adapter_apis.h @@ -55,6 +55,7 @@ ORT_API_STATUS(SessionRegisterGraphTransformers, _In_ OrtSession* session); ORT_API_STATUS(SessionRegisterCustomRegistry, _In_ OrtSession* session, _In_ IMLOperatorRegistry* registry); ORT_API_STATUS(SessionCopyOneInputAcrossDevices, _In_ OrtSession* session, _In_ const char* const input_name, _In_ OrtValue* orig_value, _Outptr_ OrtValue** new_value); ORT_API_STATUS(SessionGetNumberOfIntraOpThreads, _In_ OrtSession* session, _Out_ uint32_t* num_threads); +ORT_API_STATUS(SessionGetNamedDimensionsOverrides, _In_ OrtSession* session, _Out_ winrt::Windows::Foundation::Collections::IMapView& overrides); // Dml methods (TODO need to figure out how these need to move to session somehow...) ORT_API_STATUS(DmlExecutionProviderSetDefaultRoundingMode, _In_ OrtExecutionProvider* dml_provider, _In_ bool is_enabled); diff --git a/winml/adapter/winml_adapter_c_api.cpp b/winml/adapter/winml_adapter_c_api.cpp index 58af53d07c..a5b9d22214 100644 --- a/winml/adapter/winml_adapter_c_api.cpp +++ b/winml/adapter/winml_adapter_c_api.cpp @@ -56,6 +56,7 @@ static constexpr WinmlAdapterApi winml_adapter_api_1 = { &winmla::SessionEndProfiling, &winmla::SessionCopyOneInputAcrossDevices, &winmla::SessionGetNumberOfIntraOpThreads, + &winmla::SessionGetNamedDimensionsOverrides, // Dml methods (TODO need to figure out how these need to move to session somehow...) &winmla::DmlExecutionProviderSetDefaultRoundingMode, diff --git a/winml/adapter/winml_adapter_c_api.h b/winml/adapter/winml_adapter_c_api.h index 2e4173f344..75f7acef72 100644 --- a/winml/adapter/winml_adapter_c_api.h +++ b/winml/adapter/winml_adapter_c_api.h @@ -4,6 +4,7 @@ #pragma once #include "core/session/onnxruntime_c_api.h" +#include "winrt/windows.foundation.collections.h" /** * All APIs exported by winml_adapter_c_api.h are part of the private interface dedicated to supporting the WinML API. @@ -295,6 +296,14 @@ struct WinmlAdapterApi { */ OrtStatus*(ORT_API_CALL* SessionGetNumberOfIntraOpThreads)(_In_ OrtSession* session, _Out_ uint32_t* num_threads)NO_EXCEPTION; + /** + * SessionGetNamedDimensionsOverrides + * This api returns the named dimension overrides that are specified for this session + * + * WinML uses this to determine that named dimension overrides were set correctly through OrtSessionOptions. + */ + OrtStatus*(ORT_API_CALL* SessionGetNamedDimensionsOverrides)(_In_ OrtSession* session, _Out_ winrt::Windows::Foundation::Collections::IMapView& overrides)NO_EXCEPTION; + /** * DmlExecutionProviderSetDefaultRoundingMode * This api is used to configure the DML EP to turn on/off rounding. diff --git a/winml/adapter/winml_adapter_session.cpp b/winml/adapter/winml_adapter_session.cpp index bcb2971d28..746b449986 100644 --- a/winml/adapter/winml_adapter_session.cpp +++ b/winml/adapter/winml_adapter_session.cpp @@ -251,4 +251,21 @@ ORT_API_STATUS_IMPL(winmla::SessionGetNumberOfIntraOpThreads, _In_ OrtSession* s *num_threads = session_options.intra_op_param.thread_pool_size; return nullptr; API_IMPL_END +} + +ORT_API_STATUS_IMPL(winmla::SessionGetNamedDimensionsOverrides, _In_ OrtSession* session, _Out_ winrt::Windows::Foundation::Collections::IMapView& named_dimension_overrides) { + API_IMPL_BEGIN + auto inference_session = reinterpret_cast<::onnxruntime::InferenceSession*>(session); + auto session_options = inference_session->GetSessionOptions(); + winrt::Windows::Foundation::Collections::IMap override_map = winrt::single_threaded_map(); + for (auto freeDimOverride : session_options.free_dimension_overrides) + { + if (freeDimOverride.dim_identifer_type == onnxruntime::FreeDimensionOverrideType::Name) + { + override_map.Insert(winrt::to_hstring(freeDimOverride.dim_identifier), static_cast(freeDimOverride.dim_value)); + } + } + named_dimension_overrides = override_map.GetView(); + return nullptr; + API_IMPL_END } \ No newline at end of file diff --git a/winml/api/Microsoft.AI.MachineLearning.Experimental.idl b/winml/api/Microsoft.AI.MachineLearning.Experimental.idl index 4d38e8ea19..6eeb6d8b71 100644 --- a/winml/api/Microsoft.AI.MachineLearning.Experimental.idl +++ b/winml/api/Microsoft.AI.MachineLearning.Experimental.idl @@ -20,6 +20,7 @@ import "Windows.AI.MachineLearning.idl"; #define ROOT_NS Microsoft #endif + namespace ROOT_NS.AI.MachineLearning.Experimental { [threading(both)] @@ -30,4 +31,19 @@ namespace ROOT_NS.AI.MachineLearning.Experimental { void Test(); } + + [marshaling_behavior(agile)] + [dualapipartition(1)] + runtimeclass LearningModelSessionOptionsExperimental { + Windows.Foundation.Collections.IMapView GetNamedDimensionOverrides(); + } + + [threading(both)] + [marshaling_behavior(agile)] + [dualapipartition(1)] + runtimeclass LearningModelSessionExperimental { + LearningModelSessionExperimental(ROOT_NS.AI.MachineLearning.LearningModelSession session); + LearningModelSessionOptionsExperimental Options { get; }; + } + } // namespace Microsoft.AI.MachineLearning.Experimental \ No newline at end of file diff --git a/winml/dll/module.cpp b/winml/dll/module.cpp index de6820bdca..092621c179 100644 --- a/winml/dll/module.cpp +++ b/winml/dll/module.cpp @@ -8,6 +8,8 @@ #include "LearningModelDevice.h" #include "OnnxruntimeProvider.h" #include "Dummy.h" +#include "LearningModelSessionOptionsExperimental.h" +#include "LearningModelSessionExperimental.h" #define STRINGIFY(x) #x #define XSTRINGIFY(x) STRINGIFY(x) @@ -100,13 +102,18 @@ STDAPI DllGetExperimentalActivationFactory(void* classId, void** factory) noexce return std::equal(left.rbegin(), left.rend(), right.rbegin(), right.rend()); }; - std::wostringstream dummy_class; - dummy_class << XSTRINGIFY(WINML_ROOT_NS) << ".AI.MachineLearning.Experimental.Dummy"; - if (requal(name, dummy_class.str())) { + winrt::hstring winml_namespace = winrt::to_hstring(XSTRINGIFY(WINML_ROOT_NS)); + + if (requal(name, winml_namespace + L".AI.MachineLearning.Experimental.Dummy")) { *factory = winrt::detach_abi(winrt::make()); return 0; } + if (requal(name, winml_namespace + L".AI.MachineLearning.Experimental.LearningModelSessionExperimental")) { + *factory = winrt::detach_abi(winrt::make()); + return 0; + } + return winrt::hresult_class_not_available(name).to_abi(); } catch (...) { return winrt::to_hresult(); diff --git a/winml/lib/Api.Experimental/LearningModelSessionExperimental.cpp b/winml/lib/Api.Experimental/LearningModelSessionExperimental.cpp new file mode 100644 index 0000000000..4b3150f1f9 --- /dev/null +++ b/winml/lib/Api.Experimental/LearningModelSessionExperimental.cpp @@ -0,0 +1,18 @@ +#include "pch.h" + +#include "LearningModelSessionOptionsExperimental.h" +#include "LearningModelSessionExperimental.h" + +namespace WINML_EXPERIMENTALP { + +LearningModelSessionExperimental::LearningModelSessionExperimental(const winml::LearningModelSession& session) : _session(session) { + int i = 0; + i++; +} + + +WINML_EXPERIMENTAL::LearningModelSessionOptionsExperimental LearningModelSessionExperimental::Options() { + return winrt::make(_session); +} + +} // namespace WINML_EXPERIMENTALP \ No newline at end of file diff --git a/winml/lib/Api.Experimental/LearningModelSessionExperimental.h b/winml/lib/Api.Experimental/LearningModelSessionExperimental.h new file mode 100644 index 0000000000..ed09177fe2 --- /dev/null +++ b/winml/lib/Api.Experimental/LearningModelSessionExperimental.h @@ -0,0 +1,23 @@ +#pragma once + +#include "LearningModelSessionExperimental.g.h" + +namespace WINML_EXPERIMENTALP { + +struct LearningModelSessionExperimental : LearningModelSessionExperimentalT { + LearningModelSessionExperimental(const winml::LearningModelSession& session); + + WINML_EXPERIMENTAL::LearningModelSessionOptionsExperimental Options(); + +private: + winml::LearningModelSession _session; +}; + +} // namespace WINML_EXPERIMENTALP + +namespace WINML_EXPERIMENTAL::factory_implementation { + +struct LearningModelSessionExperimental : LearningModelSessionExperimentalT { +}; + +} // namespace WINML_EXPERIMENTAL::factory_implementation \ No newline at end of file diff --git a/winml/lib/Api.Experimental/LearningModelSessionOptionsExperimental.cpp b/winml/lib/Api.Experimental/LearningModelSessionOptionsExperimental.cpp new file mode 100644 index 0000000000..3b4f65dd86 --- /dev/null +++ b/winml/lib/Api.Experimental/LearningModelSessionOptionsExperimental.cpp @@ -0,0 +1,18 @@ +#include "pch.h" +#include "LearningModelSessionOptionsExperimental.h" +#include "winrt/Windows.Foundation.Collections.h" +#include "LearningModelSession.h" +#include "iengine.h" + +namespace WINML_EXPERIMENTALP { +LearningModelSessionOptionsExperimental::LearningModelSessionOptionsExperimental(const winml::LearningModelSession& session) { + com_ptr session_impl = session.as(); + _winml::IEngine* engine = session_impl->GetEngine(); + engine->GetNamedDimensionOverrides(overrides_); +} + +wfc::IMapView LearningModelSessionOptionsExperimental::GetNamedDimensionOverrides() { + return overrides_; +} + +} // namespace WINML_EXPERIMENTALP \ No newline at end of file diff --git a/winml/lib/Api.Experimental/LearningModelSessionOptionsExperimental.h b/winml/lib/Api.Experimental/LearningModelSessionOptionsExperimental.h new file mode 100644 index 0000000000..abeeb909fa --- /dev/null +++ b/winml/lib/Api.Experimental/LearningModelSessionOptionsExperimental.h @@ -0,0 +1,17 @@ +#pragma once + +#include "LearningModelSessionOptionsExperimental.g.h" + +namespace WINML_EXPERIMENTALP { + +struct LearningModelSessionOptionsExperimental : LearningModelSessionOptionsExperimentalT +{ + LearningModelSessionOptionsExperimental(const winml::LearningModelSession& options); + + wfc::IMapView GetNamedDimensionOverrides(); + + private: + wfc::IMapView overrides_; +}; + +} // namespace WINML_EXPERIMENTALP diff --git a/winml/lib/Api.Ort/OnnxruntimeEngine.cpp b/winml/lib/Api.Ort/OnnxruntimeEngine.cpp index 66cb317289..e3080d7839 100644 --- a/winml/lib/Api.Ort/OnnxruntimeEngine.cpp +++ b/winml/lib/Api.Ort/OnnxruntimeEngine.cpp @@ -1121,6 +1121,13 @@ HRESULT OnnxruntimeEngine::GetNumberOfIntraOpThreads(uint32_t* num_threads) return S_OK; } +HRESULT OnnxruntimeEngine::GetNamedDimensionOverrides(wfc::IMapView& overrides) { + auto ort_api = engine_factory_->UseOrtApi(); + auto winml_adapter_api = engine_factory_->UseWinmlAdapterApi(); + RETURN_HR_IF_NOT_OK_MSG(winml_adapter_api->SessionGetNamedDimensionsOverrides(session_.get(), overrides), ort_api); + return S_OK; +} + HRESULT OnnxruntimeEngine::CreateOneInputAcrossDevices(const char* name, IValue* src, IValue** out) { auto ort_api = engine_factory_->UseOrtApi(); auto winml_adapter_api = engine_factory_->UseWinmlAdapterApi(); diff --git a/winml/lib/Api.Ort/OnnxruntimeEngine.h b/winml/lib/Api.Ort/OnnxruntimeEngine.h index 368e2306f1..02032351e2 100644 --- a/winml/lib/Api.Ort/OnnxruntimeEngine.h +++ b/winml/lib/Api.Ort/OnnxruntimeEngine.h @@ -116,6 +116,9 @@ class OnnxruntimeEngine : public Microsoft::WRL::RuntimeClass< STDMETHOD(GetNumberOfIntraOpThreads) (uint32_t* num_threads) override; + STDMETHOD(GetNamedDimensionOverrides) + (wfc::IMapView& overrides) override; + OrtSession* UseOrtSession(); const OrtApi* UseOrtApi(); OnnxruntimeEngineFactory* GetEngineFactory(); diff --git a/winml/lib/Common/inc/iengine.h b/winml/lib/Common/inc/iengine.h index 37880095a0..6a7c6f71c4 100644 --- a/winml/lib/Common/inc/iengine.h +++ b/winml/lib/Common/inc/iengine.h @@ -149,6 +149,9 @@ IEngine : IUnknown { STDMETHOD(GetNumberOfIntraOpThreads) (uint32_t * num_threads) PURE; + + STDMETHOD(GetNamedDimensionOverrides) + (wfc::IMapView& overrides) PURE; }; MIDL_INTERFACE("8ac0b6b9-4561-492b-b63d-a07bdd8292c6") diff --git a/winml/test/api/LearningModelSessionAPITest.cpp b/winml/test/api/LearningModelSessionAPITest.cpp index 9c08476492..4b0d4555f9 100644 --- a/winml/test/api/LearningModelSessionAPITest.cpp +++ b/winml/test/api/LearningModelSessionAPITest.cpp @@ -326,12 +326,20 @@ static void NamedDimensionOverride() LearningModelSessionOptions options; options.OverrideNamedDimension(L"None", n); - // Verifies that if a Dim name doesn't exist the named dimension override does nothing + // Verifies that if a Dim name doesn't exist the named dimension override does not interfere with successful evaluation + // The override is still expected to be present in the internal onnxruntime override data options.OverrideNamedDimension(L"DimNameThatDoesntExist", n); LearningModelSession session(nullptr); WINML_EXPECT_NO_THROW(session = LearningModelSession(model, device, options)); + Experimental::LearningModelSessionExperimental experimental_session(session); + Experimental::LearningModelSessionOptionsExperimental experimental_options = experimental_session.Options(); + wfc::IMapView internal_overrides = experimental_options.GetNamedDimensionOverrides(); + + WINML_EXPECT_EQUAL(internal_overrides.Lookup(L"None"), n); + WINML_EXPECT_EQUAL(internal_overrides.Lookup(L"DimNameThatDoesntExist"), n); + ILearningModelFeatureDescriptor descriptor = model.InputFeatures().GetAt(0); TensorFeatureDescriptor tensorDescriptor = nullptr; descriptor.as(tensorDescriptor); diff --git a/winml/test/common/winrt_headers.h b/winml/test/common/winrt_headers.h index ff371d3635..bfe156985e 100644 --- a/winml/test/common/winrt_headers.h +++ b/winml/test/common/winrt_headers.h @@ -24,13 +24,16 @@ #define STRINGIFY(x) #x #define XSTRINGIFY(x) STRINGIFY(x) #define CPPWINRT_HEADER(root_ns) comp_generated/winrt/##root_ns##.AI.MachineLearning.h +#define CPPWINRT_EXPERIMENTAL_HEADER(root_ns) comp_generated/winrt/##root_ns##.AI.MachineLearning.Experimental.h #define NATIVE_HEADER(root_ns) root_ns##.AI.MachineLearning.native.h #define NATIVE_INTERNAL_HEADER(root_ns) root_ns##.AI.MachineLearning.native.internal.h #define CREATE_CPPWINRT_COMPONENT_HEADER() XSTRINGIFY(CPPWINRT_HEADER(WINML_ROOT_NS)) +#define CREATE_CPPWINRT_EXPERIMENTAL_COMPONENT_HEADER() XSTRINGIFY(CPPWINRT_EXPERIMENTAL_HEADER(WINML_ROOT_NS)) #define CREATE_NATIVE_HEADER() XSTRINGIFY(NATIVE_HEADER(WINML_ROOT_NS)) #define CREATE_NATIVE_INTERNAL_HEADER() XSTRINGIFY(NATIVE_INTERNAL_HEADER(WINML_ROOT_NS)) #include CREATE_CPPWINRT_COMPONENT_HEADER() +#include CREATE_CPPWINRT_EXPERIMENTAL_COMPONENT_HEADER() // WinML Native Headers #include CREATE_NATIVE_HEADER()