diff --git a/onnxruntime/core/providers/openvino/backend_manager.cc b/onnxruntime/core/providers/openvino/backend_manager.cc index 330e74ecf0461..fa23f6969b633 100644 --- a/onnxruntime/core/providers/openvino/backend_manager.cc +++ b/onnxruntime/core/providers/openvino/backend_manager.cc @@ -348,12 +348,12 @@ static void DumpOpenVINOEPModel([[maybe_unused]] const std::filesystem::path& on // this is a helper function to set the data fields, it duplicates ExternalDataInfo::SetExternalLocationToProto // but we cannot use that function as it is not part of public provider api. -static void SetExternalDataFields(ONNX_NAMESPACE::TensorProto* proto_init, const void* data_ptr, int64_t data_size) { +static void SetExternalDataFields(ONNX_NAMESPACE::TensorProto& proto_init, const void* data_ptr, int64_t data_size) { static constexpr const char* ORT_INTERNAL_MEM_INITIALIZER = "*/_ORT_MEM_ADDR_/*"; - auto* external_data = proto_init->mutable_external_data(); + auto* external_data = proto_init.mutable_external_data(); bool found_location = false, found_offset = false, found_length = false; const int ext_data_size = external_data->size(); - proto_init->set_data_location(ONNX_NAMESPACE::TensorProto_DataLocation::TensorProto_DataLocation_EXTERNAL); + proto_init.set_data_location(ONNX_NAMESPACE::TensorProto_DataLocation::TensorProto_DataLocation_EXTERNAL); for (int j = 0; j < ext_data_size; ++j) { auto& ext_entry = external_data->at(j); @@ -541,11 +541,15 @@ BackendManager::GetModelProtoFromFusedNode(const onnxruntime::Node& fused_node, if (it == proto_initializer_map.end()) continue; - auto* proto_init = it->second; + if (!it->second) { + ORT_THROW(name + " proto initializer is null!"); + } + + auto& proto_init = *it->second; // If the proto initializer is missing data, fill it in - if (!proto_init->has_raw_data() && src_init->has_raw_data()) { - *proto_init->mutable_raw_data() = src_init->raw_data(); + if (!proto_init.has_raw_data() && src_init->has_raw_data()) { + *(proto_init.mutable_raw_data()) = src_init->raw_data(); } // Only set in-memory external_data fields if the data is in memory @@ -554,10 +558,12 @@ BackendManager::GetModelProtoFromFusedNode(const onnxruntime::Node& fused_node, << src_init->name() << ", data_type: " << src_init->data_type() << ", raw_data size: " << src_init->raw_data().size(); - if (src_init->raw_data().size() > 0) - SetExternalDataFields(proto_init, src_init->raw_data().data(), src_init->raw_data().size()); - else - LOGS(logger, VERBOSE) << "Initializer has empty raw_data: skipping initializer '" << src_init->name() << "'..."; + if (src_init->raw_data().size() > 0) { + SetExternalDataFields(proto_init, src_init->raw_data().data(), src_init->raw_data().size()); + } + else { + LOGS(logger, VERBOSE) << "Initializer has empty raw_data: skipping initializer '" << src_init->name() << "'..."; + } } else if (onnxruntime::utils::HasExternalDataInMemory(*src_init)) { auto it_ext = external_initializers_offset_and_length.find(name); if (it_ext == external_initializers_offset_and_length.end()) { diff --git a/onnxruntime/test/providers/openvino/openvino_ep_ext_init.cc b/onnxruntime/test/providers/openvino/openvino_ep_ext_init.cc index 74d4172cc234c..85088e65d2db3 100644 --- a/onnxruntime/test/providers/openvino/openvino_ep_ext_init.cc +++ b/onnxruntime/test/providers/openvino/openvino_ep_ext_init.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include "core/session/onnxruntime_cxx_api.h" @@ -23,16 +24,16 @@ class OVEP_ExtInit_Tests : public ::testing::TestWithParam {}; namespace { -std::vector LoadFileToMemory(const std::string& path) { +std::optional> LoadFileToMemory(const std::string& path) { std::ifstream file(path, std::ios::binary | std::ios::ate); if (!file.is_open()) { - return std::vector(); + return std::nullopt; } std::streamsize size = file.tellg(); file.seekg(0, std::ios::beg); std::vector buffer(static_cast(size)); if (!file.read(reinterpret_cast(buffer.data()), size)) { - return std::vector(); + return std::nullopt; } return buffer; } @@ -57,8 +58,7 @@ auto ProbeDevice(const std::string& device) { namespace onnxruntime { namespace test { -// this test requires OV 2025.4+ to run -TEST_P(OVEP_ExtInit_Tests, DISABLED_ModelFromExtInit) { +TEST_P(OVEP_ExtInit_Tests, ModelFromExtInit) { const auto& device = GetParam(); if (!ProbeDevice(device)) GTEST_SKIP() << device + " is not available on this machine"; @@ -161,14 +161,15 @@ TEST_P(OVEP_ExtInit_Tests, DISABLED_ModelFromExtInit) { } // 4. Load model and weights into memory - std::vector model_data = LoadFileToMemory(model_path); - std::vector weights_data = LoadFileToMemory(weights_path); + auto model_data = LoadFileToMemory(model_path); + auto weights_data = LoadFileToMemory(weights_path); + ASSERT_TRUE(model_data.has_value() && weights_data.has_value()); // 5. Prepare external initializer info PathString weights_name_path(weights_path.begin(), weights_path.end()); std::vector names_path = {weights_name_path}; - std::vector buffers = {reinterpret_cast(weights_data.data())}; - std::vector buffer_sizes = {weights_data.size()}; + std::vector buffers = {reinterpret_cast(weights_data.value().data())}; + std::vector buffer_sizes = {weights_data.value().size()}; // 6. Set up session options with OpenVINO Ort::SessionOptions session_options; @@ -179,7 +180,7 @@ TEST_P(OVEP_ExtInit_Tests, DISABLED_ModelFromExtInit) { session_options.AddExternalInitializersFromFilesInMemory(names_path, buffers, buffer_sizes); // 7. Create session from memory - Ort::Session session(*ort_env, model_data.data(), model_data.size(), session_options); + Ort::Session session(*ort_env, model_data.value().data(), model_data.value().size(), session_options); // 8. Run inference to verify weights are loaded std::vector input_data(floats_per_initializer, 2.0f);