From 831ed21f947e3696e7de8fefb32406370248d7eb Mon Sep 17 00:00:00 2001 From: Hector Li Date: Tue, 25 Mar 2025 15:19:47 -0700 Subject: [PATCH 1/5] Add validation in path that user CreateSessionFromArray, that if ep.context_enable is set, then ep.context_file_path is expected, otherwise report error because ORT don't know where to generate the _ctx.onnx file --- onnxruntime/core/session/utils.cc | 14 +++++ .../test/providers/qnn/qnn_ep_context_test.cc | 57 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/onnxruntime/core/session/utils.cc b/onnxruntime/core/session/utils.cc index afb1ed2696c9f..2ba90069a1430 100644 --- a/onnxruntime/core/session/utils.cc +++ b/onnxruntime/core/session/utils.cc @@ -12,6 +12,7 @@ #include "core/session/onnxruntime_c_api.h" #include "core/session/ort_apis.h" #include "core/session/ort_env.h" +#include "core/session/onnxruntime_session_options_config_keys.h" using namespace onnxruntime; @@ -49,6 +50,19 @@ OrtStatus* CreateSessionAndLoadModel(_In_ const OrtSessionOptions* options, bool load_config_from_model = os_env.GetEnvironmentVar(inference_session_utils::kOrtLoadConfigFromModelEnvVar) == "1"; + // If ep.context_enable is set, then ep.context_file_path is expected, otherwise ORT don't know where to generate the _ctx.onnx file + if (options) { + auto ep_context_enable = options->value.config_options.GetConfigEntry(kOrtSessionOptionEpContextEnable); + auto ep_context_file_path = options->value.config_options.GetConfigEntry(kOrtSessionOptionEpContextFilePath); + if (ep_context_enable.has_value() && ep_context_enable.value() == "1" && (!ep_context_file_path.has_value() || + (ep_context_file_path.has_value() && ep_context_file_path.value().empty()))) { + return OrtApis::CreateStatus(ORT_FAIL, + "CreateSessionFromArray is called with ep.context_enable enabled but an \ +empty ep.context_file_path. The system does not know where to generate the \ +EP context model. Please specify a valid ep.context_file_path."); + } + } + if (load_config_from_model) { #if !defined(ORT_MINIMAL_BUILD) if (model_path != nullptr) { diff --git a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc index e39102a21dd1c..e3eeab88a03f7 100644 --- a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc +++ b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc @@ -1309,6 +1309,63 @@ TEST_F(QnnHTPBackendTests, QnnContextGenWeightSharingSessionAPI) { } ASSERT_EQ(std::remove(qnn_ctx_binary_file_name1.c_str()), 0); } + +// Session created from array wth ep.context_enable enabled without ep.context_file_path +// Error message expected +TEST_F(QnnHTPBackendTests, LoadFromArrayWithQnnEpContextGenPathValidation) { + ProviderOptions provider_options; +#if defined(_WIN32) + provider_options["backend_path"] = "QnnHtp.dll"; +#else + provider_options["backend_path"] = "libQnnHtp.so"; +#endif + const std::unordered_map domain_to_version = {{"", 13}, {kMSDomain, 1}}; + + auto& logging_manager = DefaultLoggingManager(); + logging_manager.SetDefaultLoggerSeverity(logging::Severity::kERROR); + onnxruntime::Model model("QNN_EP_TestModel", false, ModelMetaData(), PathString(), + IOnnxRuntimeOpSchemaRegistryList(), domain_to_version, {}, + logging_manager.DefaultLogger()); + Graph& graph = model.MainGraph(); + ModelTestBuilder helper(graph); + bool single_ep_node = true; + BuildGraphWithQAndNonQ(single_ep_node)(helper); + helper.SetGraphOutputs(); + ASSERT_STATUS_OK(model.MainGraph().Resolve()); + + // Serialize the model to a string. + std::string model_data; + model.ToProto().SerializeToString(&model_data); + + const auto model_data_span = AsByteSpan(model_data.data(), model_data.size()); + + const std::string context_model_file = "./qnn_context_binary_multi_partition_test.onnx"; + std::remove(context_model_file.c_str()); + Ort::SessionOptions so; + so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); + so.AppendExecutionProvider("QNN", provider_options); + + ORT_TRY { + Ort::Session session1(*ort_env, model_data_span.data(), model_data_span.size(), so); + } + ORT_CATCH(const std::exception& e) { + ORT_HANDLE_EXCEPTION([&e]() { + std::string e_message1(std::string(e.what())); + ASSERT_TRUE(e_message1.find("Please specify a valid ep.context_file_path.") != std::string::npos); + }); + } + + ORT_TRY { + so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, ""); + Ort::Session session2(*ort_env, model_data_span.data(), model_data_span.size(), so); + } + ORT_CATCH(const std::exception& ex) { + ORT_HANDLE_EXCEPTION([&ex]() { + std::string e_message2(std::string(ex.what())); + ASSERT_TRUE(e_message2.find("Please specify a valid ep.context_file_path.") != std::string::npos); + }); + } +} #endif // defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__) } // namespace test From 44cfab102bed891875336d66fb2fe9773bd0fb71 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Tue, 25 Mar 2025 17:01:52 -0700 Subject: [PATCH 2/5] format Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- onnxruntime/core/session/utils.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/onnxruntime/core/session/utils.cc b/onnxruntime/core/session/utils.cc index 2ba90069a1430..ec1377e2ac6c9 100644 --- a/onnxruntime/core/session/utils.cc +++ b/onnxruntime/core/session/utils.cc @@ -54,8 +54,7 @@ OrtStatus* CreateSessionAndLoadModel(_In_ const OrtSessionOptions* options, if (options) { auto ep_context_enable = options->value.config_options.GetConfigEntry(kOrtSessionOptionEpContextEnable); auto ep_context_file_path = options->value.config_options.GetConfigEntry(kOrtSessionOptionEpContextFilePath); - if (ep_context_enable.has_value() && ep_context_enable.value() == "1" && (!ep_context_file_path.has_value() || - (ep_context_file_path.has_value() && ep_context_file_path.value().empty()))) { + if (ep_context_enable.has_value() && ep_context_enable.value() == "1" && (!ep_context_file_path.has_value() || (ep_context_file_path.has_value() && ep_context_file_path.value().empty()))) { return OrtApis::CreateStatus(ORT_FAIL, "CreateSessionFromArray is called with ep.context_enable enabled but an \ empty ep.context_file_path. The system does not know where to generate the \ From ad820b18c76fa86eaf7d023e93700051eb0fa263 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Tue, 25 Mar 2025 17:03:05 -0700 Subject: [PATCH 3/5] fix the regression --- onnxruntime/core/session/utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/core/session/utils.cc b/onnxruntime/core/session/utils.cc index 2ba90069a1430..624d62bd9e44c 100644 --- a/onnxruntime/core/session/utils.cc +++ b/onnxruntime/core/session/utils.cc @@ -51,7 +51,7 @@ OrtStatus* CreateSessionAndLoadModel(_In_ const OrtSessionOptions* options, os_env.GetEnvironmentVar(inference_session_utils::kOrtLoadConfigFromModelEnvVar) == "1"; // If ep.context_enable is set, then ep.context_file_path is expected, otherwise ORT don't know where to generate the _ctx.onnx file - if (options) { + if (options && model_path == nullptr) { auto ep_context_enable = options->value.config_options.GetConfigEntry(kOrtSessionOptionEpContextEnable); auto ep_context_file_path = options->value.config_options.GetConfigEntry(kOrtSessionOptionEpContextFilePath); if (ep_context_enable.has_value() && ep_context_enable.value() == "1" && (!ep_context_file_path.has_value() || From a014e5f02ada9f34c599a7cebed9b7340e510a7b Mon Sep 17 00:00:00 2001 From: Hector Li Date: Wed, 26 Mar 2025 09:40:15 -0700 Subject: [PATCH 4/5] update the file clean up function --- onnxruntime/core/providers/qnn/qnn_execution_provider.cc | 6 +++--- onnxruntime/test/providers/qnn/qnn_ep_context_test.cc | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index 2606ace8127d3..4c6f55fe7e6b6 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -912,12 +912,12 @@ Status QNNExecutionProvider::CompileFromOrtGraph(const std::vector Date: Thu, 17 Apr 2025 09:49:09 -0700 Subject: [PATCH 5/5] update according review comments --- onnxruntime/core/providers/qnn/qnn_execution_provider.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index 4c6f55fe7e6b6..f045dae7b4e6a 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -910,12 +910,12 @@ Status QNNExecutionProvider::CompileFromOrtGraph(const std::vector