Skip to content

Commit 2b34773

Browse files
committed
early version, it doesn't embed initializers into the proto, but then restores the metadata so OV can read them back
Signed-off-by: bfilipek <[email protected]>
1 parent 9d56532 commit 2b34773

File tree

1 file changed

+167
-1
lines changed

1 file changed

+167
-1
lines changed

onnxruntime/core/providers/openvino/backend_manager.cc

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "core/providers/openvino/ov_versions/capability.h"
2222
#include "core/providers/openvino/qdq_transformations/qdq_stripping.h"
2323
#include "core/providers/openvino/qdq_transformations/qdq_scales_fix.h"
24+
#include "../../framework/tensorprotoutils.h"
2425

2526
namespace onnxruntime {
2627
namespace openvino_ep {
@@ -453,6 +454,46 @@ static void DumpOpenVINOEPModel([[maybe_unused]] const std::filesystem::path& on
453454
#endif
454455
}
455456

457+
static void SetExternalDataFields(ONNX_NAMESPACE::TensorProto* proto_init, const void* data_ptr, int64_t data_size) {
458+
static constexpr const char* ORT_INTERNAL_MEM_INITIALIZER = "*/_ORT_MEM_ADDR_/*";
459+
auto* external_data = proto_init->mutable_external_data();
460+
bool found_location = false, found_offset = false, found_length = false;
461+
const int ext_data_size = external_data->size();
462+
proto_init->set_data_location(ONNX_NAMESPACE::TensorProto_DataLocation::TensorProto_DataLocation_EXTERNAL);
463+
464+
for (int j = 0; j < ext_data_size; ++j) {
465+
auto& ext_entry = external_data->at(j);
466+
auto& key = *ext_entry.mutable_key();
467+
if (key == "location") {
468+
*ext_entry.mutable_value() = ORT_INTERNAL_MEM_INITIALIZER;
469+
found_location = true;
470+
} else if (key == "offset") {
471+
*ext_entry.mutable_value() = std::to_string(reinterpret_cast<uintptr_t>(data_ptr));
472+
found_offset = true;
473+
} else if (key == "length") {
474+
*ext_entry.mutable_value() = std::to_string(data_size);
475+
found_length = true;
476+
}
477+
}
478+
479+
if (!found_location) {
480+
auto* new_entry = external_data->Add();
481+
*new_entry->mutable_key() = "location";
482+
*new_entry->mutable_value() = ORT_INTERNAL_MEM_INITIALIZER;
483+
}
484+
if (!found_offset) {
485+
auto* new_entry = external_data->Add();
486+
*new_entry->mutable_key() = "offset";
487+
*new_entry->mutable_value() = std::to_string(reinterpret_cast<uintptr_t>(data_ptr));
488+
}
489+
if (!found_length) {
490+
auto* new_entry = external_data->Add();
491+
*new_entry->mutable_key() = "length";
492+
*new_entry->mutable_value() = std::to_string(data_size);
493+
}
494+
}
495+
496+
456497
std::unique_ptr<ONNX_NAMESPACE::ModelProto>
457498
BackendManager::GetModelProtoFromFusedNode(const onnxruntime::Node& fused_node,
458499
const onnxruntime::GraphViewer& subgraph,
@@ -529,12 +570,137 @@ BackendManager::GetModelProtoFromFusedNode(const onnxruntime::Node& fused_node,
529570
return model_proto;
530571
} else {
531572
LOGS_DEFAULT(INFO) << "[OpenVINO-EP] OVEP QDQ optimization pass is disabled";
573+
574+
static bool load_user_initializer_ = true;
575+
size_t userWeightsFromRawData = 0;
576+
size_t userWeightsFromExternalDataInMemory = 0;
577+
size_t allInitializersCount = 0;
578+
if (load_user_initializer_) {
579+
auto allInitializers = subgraph.GetAllInitializedTensors();
580+
allInitializersCount = allInitializers.size();
581+
582+
for (auto& entry : allInitializers) {
583+
auto* tp = entry.second;
584+
if (tp->has_raw_data()) {
585+
userWeightsFromRawData++;
586+
} else if (utils::HasExternalDataInMemory(*tp)) {
587+
userWeightsFromExternalDataInMemory++;
588+
}
589+
}
590+
}
591+
LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Loaded " << allInitializersCount << " initializers from the model. "
592+
<< userWeightsFromRawData << " from raw_data, "
593+
<< userWeightsFromExternalDataInMemory << " from external_data.";
594+
532595
auto model = subgraph.CreateModel(logger);
533596
auto model_proto = model->ToProto();
534597
model_proto->set_ir_version(ONNX_NAMESPACE::Version::IR_VERSION);
535-
subgraph.ToProto(*model_proto->mutable_graph(), true, true);
598+
subgraph.ToProto(*model_proto->mutable_graph(), /*include_initializers*/true, /*include_outer_scope_args*/true, /*execution order*/0, /*include_initializer_data*/!load_user_initializer_);
599+
536600
print_model_proto_duration();
537601
DumpOpenVINOEPModel(onnx_model_path_name, model_proto.get(), fused_node);
602+
603+
// new code:
604+
if (load_user_initializer_)
605+
{
606+
LOGS(logger, INFO) << "Initializer data is not included in the model proto. Updating metadata...";
607+
const auto& allInitializers = subgraph.GetAllInitializedTensors();
608+
auto* graph_proto = model_proto->mutable_graph();
609+
auto* proto_initializers = graph_proto->mutable_initializer();
610+
611+
// Build a map for quick lookup by name
612+
std::unordered_map<std::string, ONNX_NAMESPACE::TensorProto*> proto_initializer_map;
613+
for (int i = 0, n = proto_initializers->size(); i < n; ++i) {
614+
auto& proto_init = proto_initializers->at(i);
615+
proto_initializer_map[proto_init.name()] = &proto_init;
616+
}
617+
618+
for (const auto& init_entry : allInitializers) {
619+
const std::string& name = init_entry.first;
620+
const ONNX_NAMESPACE::TensorProto* src_init = init_entry.second;
621+
622+
auto it = proto_initializer_map.find(name);
623+
if (it == proto_initializer_map.end())
624+
continue;
625+
626+
auto* proto_init = it->second;
627+
628+
// If the proto initializer is missing data, fill it in
629+
if (!proto_init->has_raw_data() && src_init->has_raw_data()) {
630+
*proto_init->mutable_raw_data() = src_init->raw_data();
631+
}
632+
633+
// Only set in-memory external_data fields if the data is in memory
634+
if (src_init->has_raw_data()) {
635+
// Debug info for in-memory initializers
636+
LOGS(logger, VERBOSE) << "In-memory initializer RAW: "
637+
<< src_init->name()
638+
<< ", data_type: " << src_init->data_type()
639+
<< ", raw_data size: " << src_init->raw_data().size();
640+
641+
SetExternalDataFields(proto_init, src_init->raw_data().data(), src_init->raw_data().size());
642+
}
643+
else if (onnxruntime::utils::HasExternalDataInMemory(*src_init)) {
644+
645+
using mutable_proto_t = ONNX_NAMESPACE::TensorProto*;
646+
auto& mutable_proto = *const_cast<mutable_proto_t>(src_init);
647+
auto* entry_protos = mutable_proto.mutable_external_data();
648+
std::string location;
649+
size_t offset = 0;
650+
size_t length = 0;
651+
for (int i = 0; i < entry_protos->size(); i++) {
652+
auto& string_entry_proto{ entry_protos->at(i) };
653+
const auto& pb_key{ *(string_entry_proto.mutable_key()) };
654+
const auto& pb_value{ *(string_entry_proto.mutable_value()) };
655+
if (pb_key == "location") {
656+
location = pb_value;
657+
}
658+
else if (pb_key == "offset") {
659+
const auto res = std::from_chars(pb_value.data(), pb_value.data() + pb_value.size(), offset);
660+
if (res.ec != std::errc()) {
661+
LOGS(logger, ERROR) << "External data in memory has invalid offset field: "
662+
<< src_init->name() << "], location: " << location
663+
<< ", offset: " << pb_value;
664+
offset = 0;
665+
}
666+
}
667+
else if (pb_key == "length") {
668+
const auto res = std::from_chars(pb_value.data(), pb_value.data() + pb_value.size(), length);
669+
if (res.ec != std::errc()) {
670+
LOGS(logger, ERROR) << "External data in memory has invalid length field: "
671+
<< src_init->name() << "], location: " << location
672+
<< ", length: " << pb_value;
673+
offset = 0;
674+
}
675+
}
676+
}
677+
if (offset == 0 || length == 0) {
678+
LOGS(logger, ERROR) << "External data in memory has invalid external_data fields: "
679+
<< src_init->name() << "], location: " << location
680+
<< ", offset: " << offset
681+
<< ", length: " << length;
682+
}
683+
else
684+
{
685+
// we have data in it, so populate the proto_init
686+
LOGS(logger, VERBOSE) << "In-memory initializer EXT: "
687+
<< src_init->name()
688+
<< ", size: " << length;
689+
690+
SetExternalDataFields(proto_init, (const void*)offset, length);
691+
}
692+
}
693+
else {
694+
// Debug info for file-based initializers
695+
LOGS(logger, VERBOSE)<< "File-based initializer: "
696+
<< src_init->name()
697+
<< ", data_type: " << src_init->data_type();
698+
}
699+
700+
}
701+
702+
}
703+
538704
return model_proto;
539705
}
540706
}

0 commit comments

Comments
 (0)