diff --git a/src/plugins/intel_npu/src/plugin/include/model_version.hpp b/src/plugins/intel_npu/src/plugin/include/model_version.hpp new file mode 100644 index 00000000000000..52e7e204c98dc4 --- /dev/null +++ b/src/plugins/intel_npu/src/plugin/include/model_version.hpp @@ -0,0 +1,60 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include + +namespace intel_npu { + +constexpr std::string_view DELIMITER = "OVNPU"; + +constexpr int CURRENT_METAVERSION_MAJOR = 1; +constexpr int CURRENT_METAVERSION_MINOR = 0; + +struct MetadataVersion { + uint32_t major; + uint32_t minor; +}; + +struct OpenvinoVersion { + std::string version; + uint32_t size; + + OpenvinoVersion(const std::string& version); + + void read(std::istream& stream); +}; + +struct MetadataBase { + virtual void read(std::istream& stream) = 0; + virtual void write(std::ostream& stream) = 0; + virtual bool isCompatible() = 0; + virtual ~MetadataBase() = default; +}; + +template +struct Metadata : public MetadataBase {}; + +template <> +struct Metadata<1, 0> : public MetadataBase { + MetadataVersion version; + OpenvinoVersion ovVersion; + + Metadata(); + + void read(std::istream& stream) override; + + void write(std::ostream& stream) override; + + bool isCompatible() override; +}; + +std::unique_ptr createMetadata(int major, int minor); + +std::unique_ptr read_metadata_from(std::vector& blob); + +} // namespace intel_npu diff --git a/src/plugins/intel_npu/src/plugin/src/compiled_model.cpp b/src/plugins/intel_npu/src/plugin/src/compiled_model.cpp index 914879feee359f..c81a86dc55b8ea 100644 --- a/src/plugins/intel_npu/src/plugin/src/compiled_model.cpp +++ b/src/plugins/intel_npu/src/plugin/src/compiled_model.cpp @@ -14,11 +14,13 @@ #include "intel_npu/al/config/runtime.hpp" #include "intel_npu/al/icompiler.hpp" #include "intel_npu/al/itt.hpp" +#include "model_version.hpp" #include "openvino/pass/constant_folding.hpp" #include "openvino/pass/manager.hpp" #include "openvino/runtime/properties.hpp" #include "openvino/runtime/system_conf.hpp" #include "openvino/runtime/threading/executor_manager.hpp" +#include "openvino/util/common_util.hpp" #include "transformations/utils/utils.hpp" namespace { @@ -141,6 +143,14 @@ void CompiledModel::export_model(std::ostream& stream) const { _logger.debug("CompiledModel::export_model"); const auto&& blob = _compiler->getCompiledNetwork(_networkPtr); stream.write(reinterpret_cast(blob.data()), blob.size()); + + auto meta = Metadata(); + meta.write(stream); + size_t blobSizeBeforeVersioning = blob.size(); + stream.write(reinterpret_cast(&blobSizeBeforeVersioning), sizeof(blobSizeBeforeVersioning)); + + stream.write(DELIMITER.data(), DELIMITER.size()); + std::stringstream str; str << "Blob size: " << blob.size() << ", hash: " << std::hex << hash(blob); _logger.info(str.str().c_str()); diff --git a/src/plugins/intel_npu/src/plugin/src/model_version.cpp b/src/plugins/intel_npu/src/plugin/src/model_version.cpp new file mode 100644 index 00000000000000..fee9a6add5c12e --- /dev/null +++ b/src/plugins/intel_npu/src/plugin/src/model_version.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "model_version.hpp" + +#include +#include + +#include "intel_npu/utils/logger/logger.hpp" +#include "openvino/core/version.hpp" + +namespace intel_npu { + +OpenvinoVersion::OpenvinoVersion(const std::string& version) { + this->version = version; + this->size = static_cast(version.size()); +} + +void OpenvinoVersion::read(std::istream& stream) { + stream.read(reinterpret_cast(&size), sizeof(size)); + stream.read(&version[0], size); +} + +Metadata<1, 0>::Metadata() : version{1, 0}, ovVersion{ov::get_openvino_version().buildNumber} {} + +void Metadata<1, 0>::read(std::istream& stream) { + ovVersion.read(stream); +} + +void Metadata<1, 0>::write(std::ostream& stream) { + stream.write(reinterpret_cast(&version.major), sizeof(version.major)); + stream.write(reinterpret_cast(&version.minor), sizeof(version.minor)); + + stream.write(reinterpret_cast(&ovVersion.size), sizeof(ovVersion.size)); + stream.write(ovVersion.version.c_str(), ovVersion.version.size()); +} + +std::unique_ptr createMetadata(int major, int minor) { + switch (major) { + case 1: + switch (minor) { + case 0: + return std::make_unique>(); + + default: + return nullptr; + } + + default: + return nullptr; + } +} + +bool Metadata<1, 0>::isCompatible() { + // checking if we still support the format + // but is checking `Major` redundant since it's checked in createMetadata? + if (version.major != CURRENT_METAVERSION_MAJOR || version.minor != CURRENT_METAVERSION_MINOR) { + return false; + } + // checking if we can import the blob + return ovVersion.version == ov::get_openvino_version().buildNumber; +} + +std::unique_ptr read_metadata_from(std::vector& blob) { + Logger _logger("NPUPlugin", Logger::global().level()); + size_t delimiterSize = DELIMITER.size(); + std::string blobVersionHeader(delimiterSize, '\0'); + + auto metadataIterator = blob.end() - delimiterSize; + memcpy(blobVersionHeader.data(), &(*metadataIterator), delimiterSize); + if (DELIMITER != blobVersionHeader) { + _logger.error("Blob is not versioned"); + return nullptr; + } + + size_t blobDataSize; + metadataIterator -= sizeof(blobDataSize); + memcpy(&blobDataSize, &(*metadataIterator), sizeof(blobDataSize)); + + metadataIterator = blob.begin() + blobDataSize; + std::stringstream metadataStream; + metadataStream.write(reinterpret_cast(&(*metadataIterator)), + blob.end() - metadataIterator - sizeof(blobDataSize)); + + MetadataVersion metaVersion; + metadataStream.read(reinterpret_cast(&metaVersion.major), sizeof(metaVersion.major)); + metadataStream.read(reinterpret_cast(&metaVersion.minor), sizeof(metaVersion.minor)); + + auto storedMeta = createMetadata(metaVersion.major, metaVersion.minor); + if (storedMeta != nullptr) { + storedMeta->read(metadataStream); + } + return storedMeta; +} + +} // namespace intel_npu diff --git a/src/plugins/intel_npu/src/plugin/src/plugin.cpp b/src/plugins/intel_npu/src/plugin/src/plugin.cpp index 260768b3690dd1..cdd8f432bc8c46 100644 --- a/src/plugins/intel_npu/src/plugin/src/plugin.cpp +++ b/src/plugins/intel_npu/src/plugin/src/plugin.cpp @@ -14,6 +14,7 @@ #include "intel_npu/al/config/npuw.hpp" #include "intel_npu/al/config/runtime.hpp" #include "intel_npu/al/itt.hpp" +#include "model_version.hpp" #include "npuw/compiled_model.hpp" #include "openvino/op/constant.hpp" #include "openvino/op/parameter.hpp" @@ -759,6 +760,15 @@ std::shared_ptr Plugin::import_model(std::istream& stream, c } _logger.debug("Successfully read %zu bytes into blob.", graphSize); + auto storedMeta = read_metadata_from(blob); + + if (storedMeta == nullptr) { + OPENVINO_THROW("Couldn't read blob version."); + } else if (!storedMeta->isCompatible()) { + // _logger.info print for storedMeta members or use std::cout? + OPENVINO_THROW("Incompatible blob metadata version!"); + } + auto meta = compiler->parse(blob, localConfig); meta.name = "net" + std::to_string(_compiledModelLoadCounter++);