Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions onnxruntime/core/providers/openvino/backend_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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()) {
Expand Down
21 changes: 11 additions & 10 deletions onnxruntime/test/providers/openvino/openvino_ep_ext_init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <filesystem>
#include <map>
#include <string>
#include <optional>

#include "core/session/onnxruntime_cxx_api.h"

Expand All @@ -23,16 +24,16 @@ class OVEP_ExtInit_Tests : public ::testing::TestWithParam<std::string> {};

namespace {

std::vector<uint8_t> LoadFileToMemory(const std::string& path) {
std::optional<std::vector<uint8_t>> LoadFileToMemory(const std::string& path) {
std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.is_open()) {
return std::vector<uint8_t>();
return std::nullopt;
}
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> buffer(static_cast<size_t>(size));
if (!file.read(reinterpret_cast<char*>(buffer.data()), size)) {
return std::vector<uint8_t>();
return std::nullopt;
}
return buffer;
}
Expand All @@ -57,8 +58,7 @@ auto ProbeDevice(const std::string& device) {
namespace onnxruntime {
namespace test {

// this test requiresOV 2025.4+ to run, currently CI uses OV 2025.2, so the test will be disabled until OV is updated
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";
Expand Down Expand Up @@ -161,14 +161,15 @@ TEST_P(OVEP_ExtInit_Tests, DISABLED_ModelFromExtInit) {
}

// 4. Load model and weights into memory
std::vector<uint8_t> model_data = LoadFileToMemory(model_path);
std::vector<uint8_t> 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<PathString> names_path = {weights_name_path};
std::vector<char*> buffers = {reinterpret_cast<char*>(weights_data.data())};
std::vector<size_t> buffer_sizes = {weights_data.size()};
std::vector<char*> buffers = {reinterpret_cast<char*>(weights_data.value().data())};
std::vector<size_t> buffer_sizes = {weights_data.value().size()};

// 6. Set up session options with OpenVINO
Ort::SessionOptions session_options;
Expand All @@ -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<float> input_data(floats_per_initializer, 2.0f);
Expand Down
Loading