Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6a1e938
OpenVINO backend: 1) enable gpt-oss moe on OV bk; 2) enable mxfp4 sup…
zhaixuejun1993 Jun 23, 2026
667780b
OpenVINO backend: disable TOPK_MOE op test
zhaixuejun1993 Jun 24, 2026
57925d0
OpenVINO Backend: Add op FILL support
zhaixuejun1993 Jun 25, 2026
2d99fc2
OpenVINO backend: enable set rows with multi dims
zhaixuejun1993 Jun 25, 2026
53fbb6a
fix the name missmatch in setrow + view
zhaixuejun1993 Jun 25, 2026
cbcb886
OpenVINO backend: enable op GGML_UNARY_OP_SIGMOID
zhaixuejun1993 Jun 25, 2026
ca3f65f
OpenVINO Backend: enable SQR & SQRT
zhaixuejun1993 Jun 25, 2026
83f98bd
OpenVINO backend: 1) ensure unique node names for OpenVINO; 2) add or…
zhaixuejun1993 May 27, 2026
2ede174
OpenVINO backend: enable fallback for openVINO to CPU backend
zhaixuejun1993 May 27, 2026
a91e779
OpenVINO backend: fix accurace issue in gemma3n arch test
zhaixuejun1993 Jun 30, 2026
9f60666
fix mpt failed case
zhaixuejun1993 Jun 30, 2026
27ccd51
OpenVINO backend: clean nodeinfo
zhaixuejun1993 Jul 3, 2026
d69d79c
Merge pull request #239 from zhaixuejun1993/xuejun/remove_node_output…
zhaixuejun1993 Jul 3, 2026
c872f4c
OpenVINO Backend: enable zero-size copy for view
zhaixuejun1993 Jul 7, 2026
887dade
Merge pull request #243 from zhaixuejun1993/xuejun/fix-view_cpy-issue
zhaixuejun1993 Jul 7, 2026
75ff066
add concat ssm_conv in compute_dynamic_dim
wine99 May 21, 2026
30c0bcb
OpenVINO backend: disable EXP with FP32, which failed in op test. Roo…
zhaixuejun1993 Jun 16, 2026
842ee70
OpenVINO backend: fix CPY op test failed issue
zhaixuejun1993 Jun 16, 2026
612ccf7
OpenVINO backend: fix GATED_DELTA_NET op test failed issue
zhaixuejun1993 Jun 16, 2026
0c67d7f
handle in-place op, handle qwen35 dynamic clearing of cache in cgraph
wine99 Jun 18, 2026
2b28da4
handle qwen35 dynamic clearing of cache correctly
wine99 Jun 23, 2026
4cd88eb
Enable qwen35 dense multi seq
wine99 Jun 29, 2026
7631cf3
Fix qwen35 9b gqa
wine99 Jun 30, 2026
f0135e3
Fix after rebase
wine99 Jul 1, 2026
0bf9b5c
Disable SOLVE_TRI
wine99 Jul 7, 2026
4102b17
openvino: fix NEOX RoPE accuracy on GPU stateful (mixed-rank Multiply)
cavusmustafa Jul 7, 2026
49852ce
OpenVINO backend: 1) remove the unique name in llama.cpp; 2) add new …
zhaixuejun1993 Jul 8, 2026
8145086
OpenVINO Backenb: remove changes in llama.cpp
zhaixuejun1993 Jul 8, 2026
eed038c
Merge pull request #246 from zhaixuejun1993/xuejun/fix-arch-issues
zhaixuejun1993 Jul 9, 2026
63e44c9
Merge pull request #247 from zhaixuejun1993/xuejun/remove-changes-in-…
zhaixuejun1993 Jul 9, 2026
c7a5756
OpenVINO Backend: cache key upgrade includes all src name
zhaixuejun1993 Jul 9, 2026
131e9fc
Doc change (use x64 Native Tools Command Prompt for VS)
virajwad Jul 9, 2026
810fffd
Cleaner sentence
virajwad Jul 9, 2026
c6311c3
Merge pull request #249 from ravi9/build_doc_change
ravi9 Jul 9, 2026
54a993d
Merge pull request #248 from zhaixuejun1993/xuejun/remove-flag
zhaixuejun1993 Jul 10, 2026
8812179
OpenVINO Backend: enable llama arch test on ci
zhaixuejun1993 Jul 10, 2026
7a9b001
Merge pull request #250 from zhaixuejun1993/xuejun/enable-ci-arch-test
zhaixuejun1993 Jul 10, 2026
795d323
OpenVINO Backend: move parameter node creating from decoder into tran…
zhaixuejun1993 Jul 3, 2026
796fce0
OpenVINO Backend: create extra input ov node move from decoder to tra…
zhaixuejun1993 Jul 3, 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
9 changes: 3 additions & 6 deletions .github/workflows/build-openvino.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,16 @@ jobs:

- name: Test (CPU)
id: cmake_test_cpu
# TODO: fix and re-enable the `test-llama-archs` test below
run: |
cd ${{ github.workspace }}
ctest --test-dir build/ReleaseOV -L main -E "test-llama-archs" --verbose --timeout 2000
ctest --test-dir build/ReleaseOV -L main --verbose --timeout 2000

- name: Test (GPU)
id: cmake_test_gpu
# TODO: fix and re-enable the `test-llama-archs` test below
run: |
cd ${{ github.workspace }}
export GGML_OPENVINO_DEVICE=GPU
ctest --test-dir build/ReleaseOV -L main -E "test-llama-archs" --verbose --timeout 3000
ctest --test-dir build/ReleaseOV -L main --verbose --timeout 3000

openvino-windows-2022:
runs-on: windows-2022
Expand Down Expand Up @@ -159,11 +157,10 @@ jobs:
- name: Test (CPU)
id: cmake_test_cpu
shell: cmd
# TODO: fix and re-enable the `test-llama-archs` test below
run: |
REM Find extracted OpenVINO folder dynamically
for /d %%i in (openvino_toolkit\*) do set OPENVINO_ROOT=%%i
call "%OPENVINO_ROOT%\setupvars.bat"

cd build
ctest --test-dir ReleaseOV -L main -E "test-llama-archs" -C Release --verbose --timeout 3000
ctest --test-dir ReleaseOV -L main -C Release --verbose --timeout 3000
2 changes: 1 addition & 1 deletion docs/backend/OPENVINO.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ cmake -B build/ReleaseOV -G Ninja -DCMAKE_BUILD_TYPE=Release -DGGML_OPENVINO=ON
cmake --build build/ReleaseOV --parallel
```

- **Windows:** Open a **Developer Command Prompt for VS 2022** (so the MSVC toolchain is on `PATH`), then run:
- **Windows:** Open **x64 Native Tools Command Prompt for VS** (so the MSVC toolchain is on `PATH`), then run:

```cmd
C:\Intel\openvino\setupvars.bat
Expand Down
323 changes: 251 additions & 72 deletions ggml/src/ggml-openvino/ggml-decoder.cpp

Large diffs are not rendered by default.

75 changes: 60 additions & 15 deletions ggml/src/ggml-openvino/ggml-decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct ModelParams {
int n_seq = 1;
int n_heads_kv = -1;
int head_size = -1;
int state_size = -1; // for SSM molels, eg qwen35
int32_t rope_params[15];
bool mixed_rope_params = false;
std::vector<int> swa_layers;
Expand Down Expand Up @@ -48,6 +49,37 @@ struct ComputeParams {
int token_len_per_seq = -1;
int past_kv_len = -1;
int output_len = 1;

int cache_rs_reset_idx = -1;
int cache_rs_reset_len = -1;
// SSM/DeltaNet models otionally clear cache_r and cache_s of certain slots in the cgraph
// 3: [ 18432, 4, 1, 1] RESHAPE cache_r_l0 (reshaped)
// [ 18432, 4, 1, 1] 0: NONE cache_r_l0
// 4: [ 18432, 1, 1, 1] VIEW cache_r_l0 (reshaped) (view)
// [ 18432, 4, 1, 1] 0: RESHAPE cache_r_l0 (reshaped)
// 5: [ 18432, 1, 1, 1] SCALE cache_r_l0 (reshaped) (view) (view)
// [ 18432, 1, 1, 1] 0: VIEW cache_r_l0 (reshaped) (view)

int s_copy_active_slot_idx = -1;
int s_copy_active_slot_len = -1;
// SSM/DeltaNet models otionally reorder slots of state cache, to make the active slots contiguous
// leaf_5 is the inp->s_copy in llama-graph.cpp, eg if there are 8 slots in total and slot 3 and 7
// are active in the current batch, leaf_5 will be [3, 7, 5, 6, 4]
// 6: [ 2, 1, 1, 1] VIEW (view)
// [ 2, 1, 1, 1] 0: NONE leaf_5
// 7: [ 18432, 2, 1, 1] GET_ROWS conv_states-0
// [ 18432, 4, 1, 1] 0: RESHAPE cache_r_l0 (reshaped)
// [ 2, 1, 1, 1] 1: VIEW (view)
// 8: [ 0, 1, 1, 1] VIEW (view)
// [ 2, 1, 1, 1] 0: NONE leaf_5
// 9: [ 18432, 0, 1, 1] GET_ROWS node_9
// [ 18432, 4, 1, 1] 0: RESHAPE cache_r_l0 (reshaped)
// [ 0, 1, 1, 1] 1: VIEW (view)
// 10: [ 18432, 0, 1, 1] VIEW cache_r_l0 (view)
// [ 18432, 4, 1, 1] 0: NONE cache_r_l0
// 11: [ 18432, 0, 1, 1] CPY cache_r_l0 (view) (copy of )
// [ 18432, 0, 1, 1] 0: GET_ROWS node_9
// [ 18432, 0, 1, 1] 1: VIEW cache_r_l0 (view)
};

class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {
Expand All @@ -59,8 +91,6 @@ class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {
std::map<std::string, ggml_tensor *> node_inputs;
std::map<std::string, std::vector<std::pair<std::string, ggml_tensor *>>> node_inputs_views;
std::vector<std::string> node_inputs_names;
ggml_tensor * node_output;
std::string node_output_name;
int node_op_case = 0;
void * data_addr;
};
Expand Down Expand Up @@ -156,6 +186,10 @@ class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {

virtual std::vector<std::string> get_output_names(int node_idx) const override;

virtual std::string get_inplace_op_src(int node_idx) const override;

virtual bool is_view_like_alias_of(int node_idx, const std::string & view_src_name) const override;

virtual const std::string & get_op_type() const override;

virtual const std::string & get_op_type(int node_idx) const override;
Expand All @@ -173,23 +207,19 @@ class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {

virtual int get_op_case(int node_idx) const override { return m_node_info_list[node_idx].node_op_case; }

virtual const std::map<std::string, std::shared_ptr<ov::Node>> & get_model_inputs() const override {
virtual const std::map<std::string, ov::frontend::ggml::ModelInputInfo> & get_model_inputs() const override {
return m_model_inputs;
}

virtual const std::map<std::string, std::shared_ptr<ov::Node>> & get_model_extra_inputs() const override {
virtual const std::map<std::string, ov::frontend::ggml::ModelExtraInputInfo> & get_model_extra_inputs() const override {
return m_model_extra_inputs;
}

virtual const std::map<std::string, std::shared_ptr<ov::Tensor>> & get_model_extra_input_values() const {
return m_model_extra_input_values;
}

virtual const std::map<std::string, std::shared_ptr<ov::Node>> & get_model_weights() const override {
return m_model_weights;
}

virtual std::vector<std::string> get_model_output_names() const override { return m_model_output_names; }
virtual std::set<std::string> get_model_output_names() const override { return m_model_output_names; }

const std::map<std::string, ggml_tensor *> & get_model_outputs() const { return m_model_outputs; }

Expand All @@ -214,6 +244,8 @@ class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {

virtual bool has_mixed_rope_params() const override { return m_model_params.mixed_rope_params; }

virtual int get_ssm_state_size() const override { return m_model_params.state_size; }

virtual std::map<std::string, std::string> get_kv_param_res_names() const override;

virtual bool is_static() const override { return m_is_static; }
Expand Down Expand Up @@ -287,8 +319,12 @@ class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {
return op->op == GGML_OP_ROPE && tensor == op->src[2];
}

// also returns true for cache_s and cache_r in SSM/DeltaNet models
inline static bool is_kvcache(const ggml_tensor * tensor, const ggml_tensor * op) {
return tensor->buffer->usage == GGML_BACKEND_BUFFER_USAGE_ANY ||
if (tensor == nullptr) {
return false;
}
return (tensor->buffer != nullptr && tensor->buffer->usage == GGML_BACKEND_BUFFER_USAGE_ANY) ||
(op != nullptr && op->op == GGML_OP_SET_ROWS && op->src[2] == tensor);
}

Expand All @@ -301,7 +337,13 @@ class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {
op->src[1]->op == GGML_OP_NONE;
}

std::string get_graph_input_ov_name(const ggml_tensor * tensor, const ggml_tensor * op) {
// the state permutation index input used in SSM/DeltaNet models (inp->s_copy in llama-graph.cpp)
inline static bool is_inp_s_copy(const ggml_tensor * tensor, const ggml_tensor * op) {
return op->op == GGML_OP_GET_ROWS && tensor == op->src[1] &&
op->src[0]->buffer->usage == GGML_BACKEND_BUFFER_USAGE_ANY;
}

std::string get_graph_input_ov_name(const ggml_tensor * tensor, const ggml_tensor * op) const {
if (is_inp_pos(tensor, op)) {
return "inp_pos";
}
Expand All @@ -321,6 +363,10 @@ class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {
void compute_model_inputs();
void compute_model_outputs();

// True if tensor is the inp->s_copy index leaf gathered by a recurrent state cache GET_ROWS
// (possibly through a VIEW), so it gets a dynamic [1,1,1,-1] graph-input shape.
bool is_s_copy_leaf(const ggml_tensor * tensor) const;

// Infer and propagate dynamic-dimension indices for all tensors in the GGML graph.
void compute_node_dynamic_dims();

Expand All @@ -329,12 +375,11 @@ class GgmlOvDecoder : public ov::frontend::ggml::GgmlDecoder {
ggml_cgraph * m_cgraph = nullptr;
std::map<std::string, ggml_tensor *> m_inputs;

std::map<std::string, std::shared_ptr<ov::Node>> m_model_inputs;
std::map<std::string, std::shared_ptr<ov::Node>> m_model_extra_inputs;
std::map<std::string, std::shared_ptr<ov::Tensor>> m_model_extra_input_values;
std::map<std::string, ov::frontend::ggml::ModelInputInfo> m_model_inputs;
std::map<std::string, ov::frontend::ggml::ModelExtraInputInfo> m_model_extra_inputs;
std::map<std::string, std::shared_ptr<ov::Node>> m_model_weights;
std::map<std::string, ggml_tensor *> m_model_outputs;
std::vector<std::string> m_model_output_names;
std::set<std::string> m_model_output_names;
std::vector<NodeInfo> m_node_info_list;
std::map<ggml_tensor *, int> m_node_dynamic_dims;

Expand Down
23 changes: 19 additions & 4 deletions ggml/src/ggml-openvino/ggml-openvino-extra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,24 @@ ggml_openvino_extracted_layout ggml_openvino_get_extracted_layout(const ggml_ten
return layout;
}

// Only handle 2D weight tensors
if (tensor->ne[2] != 1 || tensor->ne[3] != 1) {
// Most quantized weights use the existing 2D extraction path. MXFP4 also
// appears as 3D expert weights for MUL_MAT_ID, so allow that type through.
if (tensor->type != GGML_TYPE_MXFP4 && (tensor->ne[2] != 1 || tensor->ne[3] != 1)) {
return layout;
}

int64_t n_elements = ggml_nelements(tensor);
const size_t alignment = 64; // Good for SIMD

if (tensor->type == GGML_TYPE_MXFP4 && (tensor->ne[2] > 1 || tensor->ne[3] > 1)) {
layout.weights_per_block = 32;
layout.is_symmetric = true;
layout.weights_size = ggml_nbytes(tensor);
layout.weights_offset = 0;
layout.total_size = layout.weights_size;
return layout;
}

// Check if requantization is needed (NPU-specific)
auto requant_type = ggml_openvino_get_requant_type(tensor, use_bias);
if (requant_type.has_value()) {
Expand Down Expand Up @@ -334,6 +344,11 @@ ggml_openvino_extracted_layout ggml_openvino_get_extracted_layout(const ggml_ten
layout.is_symmetric = false;

switch (tensor->type) {
case GGML_TYPE_MXFP4:
layout.is_u4 = true;
layout.is_symmetric = true;
break;

case GGML_TYPE_Q4_0:
layout.is_u4 = true;
layout.is_symmetric = true;
Expand Down Expand Up @@ -369,9 +384,9 @@ ggml_openvino_extracted_layout ggml_openvino_get_extracted_layout(const ggml_ten
// Weights: U4 = n_elements/2 bytes, U8 = n_elements bytes
layout.weights_size = layout.is_u4 ? (n_elements / 2) : n_elements;

// Scales: F16 per block
// Scales: F16 per block, except MXFP4 which stores one E8M0 byte per block.
int64_t n_blocks = n_elements / layout.weights_per_block;
layout.scales_size = n_blocks * sizeof(uint16_t); // F16 = 2 bytes
layout.scales_size = n_blocks * (tensor->type == GGML_TYPE_MXFP4 ? sizeof(uint8_t) : sizeof(uint16_t));
// For symmetric quantization, no zp needed (weights stored as signed)
if (layout.is_symmetric) {
layout.zp_size = 0;
Expand Down
Loading
Loading