Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
56444f7
move DynamicGraph::execute to DynamicPipeline::push
DanLiu2Intel May 27, 2026
507973b
move predict_output_shape as a DynamicPipeline static func
DanLiu2Intel May 27, 2026
f80ee45
Remove DynamicGraph::GraphArguments and use NetworkMeta instead
DanLiu2Intel May 27, 2026
1be4f64
clean IDynamicGraph
DanLiu2Intel May 27, 2026
02e4f71
restore idynamicGraph usage
DanLiu2Intel May 29, 2026
62c8846
merge dynamic arguments and update file
DanLiu2Intel Jun 1, 2026
8871937
remove DynamicGraphImpl
DanLiu2Intel Jun 4, 2026
e83de2b
move memrefImpl
DanLiu2Intel Jun 6, 2026
4c18b81
fix comments and clang
DanLiu2Intel Jun 8, 2026
24c7606
fix ai comments
DanLiu2Intel Jun 8, 2026
6734e13
update binding init and local var in dynamic pipeline and remove unne…
DanLiu2Intel Jun 9, 2026
0457010
remove idynamicGraph, update igraph::get_handle and add numberOfSubgr…
DanLiu2Intel Jun 9, 2026
6838a2c
Merge branch 'master' into master_refactorDynamicGraph
DanLiu2Intel Jun 10, 2026
ee02c61
fix ai comments to update profiling+PERF_COUNT and lp stride calculation
DanLiu2Intel Jun 10, 2026
b5f7a04
update type name, add vm content init before predict shape, move dyna…
DanLiu2Intel Jun 13, 2026
60e43d7
move DynamicArgumentsImpl to DynamicArguments and remove npu_vm_runti…
DanLiu2Intel Jun 15, 2026
16beb9f
move npu_vm_runtime.hpp to utils/vm
DanLiu2Intel Jun 18, 2026
852a935
Merge branch 'master' into master_refactorDynamicGraph
DanLiu2Intel Jun 22, 2026
b59c183
Merge branch 'master' into master_refactorDynamicGraph
DanLiu2Intel Jun 29, 2026
1e84d1a
chore: resolve merge conflict with master
DanLiu2Intel Jul 2, 2026
4bf8248
update cmakelist
DanLiu2Intel Jul 2, 2026
6f4aa22
remove accidental updates
DanLiu2Intel Jul 2, 2026
5eb56d0
fix predict issue in PR36682
DanLiu2Intel Jul 3, 2026
a9ab9f6
Merge branch 'master' into master_refactorDynamicGraph
DanLiu2Intel Jul 6, 2026
1e83127
Merge branch 'master' into master_refactorDynamicGraph
DanLiu2Intel Jul 7, 2026
f142d3d
Merge branch 'master' into master_refactorDynamicGraph
DanLiu2Intel Jul 9, 2026
957f1d8
Merge branch 'master' into master_refactorDynamicGraph
DanLiu2Intel Jul 10, 2026
717e9d1
Merge branch 'master' into master_refactorDynamicGraph
DanLiu2Intel Jul 14, 2026
ac57af8
remove Runtimecontent from DynamicArguments and split memref and ovsh…
DanLiu2Intel Jul 13, 2026
f6373d8
restrict runtime content within dynamicpipeline and update pipeline c…
DanLiu2Intel Jul 15, 2026
bc5e122
add overwrite prepareOutput and merge update_tensor to prepareOutput
DanLiu2Intel Jul 15, 2026
c773ddf
update file name
DanLiu2Intel Jul 17, 2026
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
1 change: 0 additions & 1 deletion src/plugins/intel_npu/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ add_subdirectory(ops)

if (ENABLE_NPU_PLUGIN_ENGINE)
add_subdirectory(common)
add_subdirectory(vm)
add_subdirectory(compiler_adapter)
add_subdirectory(backend)
add_subdirectory(plugin)
Expand Down
5 changes: 3 additions & 2 deletions src/plugins/intel_npu/src/backend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ file(GLOB_RECURSE SOURCES *.cpp *.hpp *.h)

source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})

add_library(${TARGET_NAME} STATIC ${SOURCES})
add_library(${TARGET_NAME} STATIC ${SOURCES} $<TARGET_OBJECTS:openvino_npu_vm_utils>)

Comment thread
DanLiu2Intel marked this conversation as resolved.
set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO})
ov_add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME})
Expand All @@ -20,13 +20,14 @@ target_compile_definitions(${TARGET_NAME}
target_include_directories(${TARGET_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE
$<TARGET_PROPERTY:openvino_npu_vm_utils,INTERFACE_INCLUDE_DIRECTORIES>
)

target_link_libraries(${TARGET_NAME}
PRIVATE
openvino_npu_common
openvino::npu_al
openvino::npu_vm_runtime_api
)
#
# targets install
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,19 @@ class ZeroDynamicInferRequest final : public ZeroInferRequest {
const std::vector<ov::SoPtr<ov::ITensor>>& tensors,
const std::optional<size_t>& batchSize = std::nullopt) override;

void predict_shapes(std::vector<IDynamicGraph::MemRefType>& outputProps);
void check_tensor_and_predicted_shapes(const std::vector<IDynamicGraph::MemRefType>& outputProps);
// Overrides the base allocation-only implementation to also resize Level Zero output buffers to the
// predicted shapes (merging the former update_tensor step) and refresh the graph arguments in one pass.
void prepare_outputs() override;

void update_tensor(const std::vector<IDynamicGraph::MemRefType>& outputProps);
void predict_output_shapes(std::vector<ov::Shape>& predictedShapes);
void check_tensor_and_predicted_shapes(const std::vector<ov::Shape>& predictedShapes);

bool _isTensorChanged = false;

private:
std::shared_ptr<IDynamicGraph::GraphArguments> _binding;
// Predicted output shapes for the current inference. Filled by predict_output_shapes(), consumed by
// check_tensor_and_predicted_shapes() and prepare_outputs().
std::vector<ov::Shape> _predictedShapes;
};

} // namespace intel_npu
121 changes: 91 additions & 30 deletions src/plugins/intel_npu/src/backend/include/zero_dynamic_pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,58 @@

#pragma once

#include "intel_npu/common/idynamic_graph.hpp"
#include "intel_npu/common/network_metadata.hpp"
#include "intel_npu/utils/vm/mem_ref_type.hpp"
#include "zero_pipeline.hpp"

namespace intel_npu {

// VM runtime execution context owner. The handle is created lazily and shared between
// shape prediction (infer request) and execution (pipeline) so the same context is reused.
struct VMExecutionContext {
npu_vm_runtime_execution_context_handle_t _handle = nullptr;

VMExecutionContext() = default;
VMExecutionContext(const VMExecutionContext&) = delete;
VMExecutionContext& operator=(const VMExecutionContext&) = delete;
VMExecutionContext(VMExecutionContext&&) = delete;
VMExecutionContext& operator=(VMExecutionContext&&) = delete;
~VMExecutionContext();

// Create the context for vmRuntime if not created yet; returns the handle.
npu_vm_runtime_execution_context_handle_t ensure(npu_vm_runtime_handle_t vmRuntime);
};

struct DynamicArguments {
std::vector<MemRefType> _inputsMemRef;
std::vector<MemRefType> _outputsMemRef;

// True once the command lists have been recorded by a first npuVMRuntimeExecute call. Subsequent
// executions can be replayed without re-recording when no tensor changed (see execute_vm_runtime).
bool _commandListsRecorded = false;

DynamicArguments() = default;
DynamicArguments(const DynamicArguments&) = delete;
DynamicArguments& operator=(const DynamicArguments&) = delete;
DynamicArguments(DynamicArguments&&) = delete;
DynamicArguments& operator=(DynamicArguments&&) = delete;
~DynamicArguments() = default;

void setArgumentProperties(uint32_t argi,
const void* argv,
const ov::Shape& shapes,
const std::vector<size_t>& strides);
};

class DynamicPipeline final : public IPipeline {
struct PipelinedCommandLists {
mutable std::shared_ptr<IDynamicGraph::GraphArguments> _binding;
std::shared_ptr<DynamicArguments> _arguments;

std::vector<std::unique_ptr<CommandList>> _commandLists;
// Store command list handles to pass it to ExecutionEngine
std::vector<ze_command_list_handle_t> _commandListHandles;

PipelinedCommandLists(size_t numCommandLists,
const std::shared_ptr<ZeroInitStructsHolder>& init_structs,
std::shared_ptr<IDynamicGraph::GraphArguments> requestBinding) {
PipelinedCommandLists(size_t numCommandLists, const std::shared_ptr<ZeroInitStructsHolder>& init_structs) {
_commandLists.reserve(numCommandLists);
for (size_t i = 0; i < numCommandLists; i++) {
_commandLists.emplace_back(std::make_unique<CommandList>(init_structs));
Expand All @@ -28,9 +64,8 @@ class DynamicPipeline final : public IPipeline {
for (size_t i = 0; i < numCommandLists; i++) {
_commandListHandles.push_back(_commandLists[i]->handle());
}
if (requestBinding != nullptr) {
_binding = requestBinding;
}

_arguments = std::make_shared<DynamicArguments>();
}

size_t size() const {
Expand All @@ -41,45 +76,57 @@ class DynamicPipeline final : public IPipeline {
return _commandListHandles.data();
}

void bind(IDynamicGraph* graph) {
if (_binding == nullptr) {
_binding = std::make_shared<IDynamicGraph::GraphArguments>();
graph->getBinding(*_binding);
// Use metadata to initialize, which will later be updated again by setArgumentProperties
void initArguments(const NetworkMetadata& metadata) {
_arguments->_inputsMemRef.resize(metadata.inputs.size());
auto& inputs = _arguments->_inputsMemRef;
for (size_t i = 0; i < inputs.size(); ++i) {
// Use size as placeholder of stride
// For now, only considering the usage and subsequent comparison of shape, and strides
const auto& shape = metadata.inputs[i].shapeFromCompiler.get_shape();
inputs[i]._dimsCount = static_cast<int64_t>(shape.size());
inputs[i]._sizes.assign(shape.begin(), shape.end());
inputs[i]._strides.resize(shape.size());
inputs[i].updateStride();
}

_arguments->_outputsMemRef.resize(metadata.outputs.size());
auto& outputs = _arguments->_outputsMemRef;
for (size_t i = 0; i < outputs.size(); ++i) {
const auto& shape = metadata.outputs[i].shapeFromCompiler.get_shape();
outputs[i]._dimsCount = static_cast<int64_t>(shape.size());
outputs[i]._sizes.assign(shape.begin(), shape.end());
outputs[i]._strides.resize(shape.size());
outputs[i].updateStride();
}
}

std::vector<ze_command_list_handle_t>& getHandles() {
return _commandListHandles;
}

IDynamicGraph::GraphArguments& getBinding() {
return *_binding;
DynamicArguments& getArguments() {
return *_arguments;
}

void updateMutableCommandList(uint32_t arg_index,
const void* arg_value,
const ov::Strides& strides,
const ov::Shape& shapes) {
// The strides are already divided by element size
if (arg_index < _binding->_inputs.size()) {
_binding->_inputs[arg_index].setArg(arg_value);
_binding->_inputs[arg_index].setSize(shapes);
_binding->_inputs[arg_index].setStrides(strides);
if (arg_index < _arguments->_inputsMemRef.size()) {
_arguments->_inputsMemRef[arg_index].setArg(arg_value);
_arguments->_inputsMemRef[arg_index].setSize(shapes);
_arguments->_inputsMemRef[arg_index].setStrides(strides);
} else {
size_t output_index = static_cast<size_t>(arg_index) - _binding->_inputs.size();
if (output_index < _binding->_outputs.size()) {
_binding->_outputs[output_index].setArg(arg_value);
_binding->_outputs[output_index].setSize(shapes);
_binding->_outputs[output_index].setStrides(strides);
size_t output_index = static_cast<size_t>(arg_index) - _arguments->_inputsMemRef.size();
if (output_index < _arguments->_outputsMemRef.size()) {
_arguments->_outputsMemRef[output_index].setArg(arg_value);
_arguments->_outputsMemRef[output_index].setSize(shapes);
_arguments->_outputsMemRef[output_index].setStrides(strides);
}
}
}

void resetCommandList() {
for (auto& cmd_list : _commandLists) {
cmd_list->reset();
}
}
};

public:
Expand All @@ -88,7 +135,6 @@ class DynamicPipeline final : public IPipeline {
const Config& config,
const std::vector<std::vector<std::shared_ptr<ZeroTensor>>>& input_tensors,
const std::vector<std::shared_ptr<ZeroTensor>>& output_tensors,
std::shared_ptr<IDynamicGraph::GraphArguments> requestBinding,
size_t batch_size = 1);

DynamicPipeline(const DynamicPipeline&) = delete;
Expand All @@ -106,7 +152,22 @@ class DynamicPipeline final : public IPipeline {
size_t batch_index,
const std::shared_ptr<ov::ITensor>& userTensor = nullptr) override;

// Predicts VM runtime output shapes for the given input/output tensors. A nullptr tensor entry falls
// back to the graph metadata max shape. Uses the pipeline's own graph handle and VM execution context,
// which is the same context reused by execute_vm_runtime.
std::vector<ov::Shape> predict_output_shapes(const std::vector<std::shared_ptr<ov::ITensor>>& inputTensors,
const std::vector<std::shared_ptr<ov::ITensor>>& outputTensors);

private:
void execute_vm_runtime(npu_vm_runtime_handle_t vmRuntime,
DynamicArguments& args,
std::vector<ze_command_list_handle_t>& commandLists,
ze_command_queue_handle_t commandQueue,
ze_fence_handle_t fence,
ze_event_handle_t event);
Comment thread
DanLiu2Intel marked this conversation as resolved.

// VM execution context owned by this pipeline; shared between shape prediction and execution.
VMExecutionContext _executionContext;
std::vector<std::unique_ptr<PipelinedCommandLists>> _command_lists;
};

Expand Down
8 changes: 8 additions & 0 deletions src/plugins/intel_npu/src/backend/include/zero_pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#pragma once

#include <vector>

#include "intel_npu/common/igraph.hpp"
#include "intel_npu/utils/zero/zero_tensor.hpp"
#include "intel_npu/utils/zero/zero_wrappers.hpp"
Expand Down Expand Up @@ -43,6 +45,12 @@ class IPipeline {
protected:
void enable_profiling();

// Helper function handling strides for Zero Pipeline and ZeroDynamicPipeline. Stateless regarding pipeline
// instances, hence static
static std::vector<size_t> get_strides(const std::vector<size_t>& strides_in_bytes,
size_t element_size,
bool reverse_order = false);

std::shared_ptr<ZeroInitStructsHolder> _init_structs;
std::shared_ptr<IGraph> _graph;
const Config _config;
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/intel_npu/src/backend/src/zero_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "zero_device.hpp"

#include "intel_npu/common/igraph.hpp"
#include "intel_npu/common/itt.hpp"
#include "intel_npu/utils/zero/zero_api.hpp"
#include "intel_npu/utils/zero/zero_utils.hpp"
Expand Down Expand Up @@ -185,7 +186,7 @@ ov::device::Type ZeroDevice::getDeviceType() const {

std::shared_ptr<InferRequest> ZeroDevice::createInferRequest(const std::shared_ptr<const ICompiledModel>& compiledModel,
const Config& config) {
if (dynamic_cast<IDynamicGraph*>(compiledModel->get_graph().get())) {
if (compiledModel->get_graph()->is_dynamic()) {
return std::make_shared<ZeroDynamicInferRequest>(_initStructs, compiledModel, config);
}
return std::make_shared<ZeroInferRequest>(_initStructs, compiledModel, config);
Expand Down
Loading
Loading