char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Zijun Yuopenvino: OV 2026.2, context-shift, Q5_1 support, gemma4 dense/embedding, and -fa off (#24503)890f1a27e

char/aliceai-t5-moe
4.8 KiB120 linesraw
1#include "../node_context.h"
2#include "../op_table.h"
3#include "../utils.h"
4#include "ggml-impl.h"
5
6#include <cstddef>
7#include <memory>
8#include <openvino/core/shape.hpp>
9#include <openvino/core/strides.hpp>
10#include <openvino/op/constant.hpp>
11#include <openvino/op/convert.hpp>
12#include <openvino/op/extractimagepatches.hpp>
13#include <openvino/op/pad.hpp>
14#include <openvino/op/reshape.hpp>
15#include <openvino/op/transpose.hpp>
16#include <openvino/op/util/attr_types.hpp>
17
18namespace ov {
19namespace frontend {
20namespace ggml {
21namespace op {
22
23OutputVector translate_im2col(const NodeContext & context) {
24    num_inputs_check(context, 2, 2);
25    const int32_t * params = context.get_output_op_params();
26    int32_t s0 = params[0];
27    int32_t s1 = params[1];
28    int32_t p0 = params[2];
29    int32_t p1 = params[3];
30    int32_t d0 = params[4];
31    int32_t d1 = params[5];
32    bool is_2D = params[6] == 1;
33    ov::Output<Node> res;
34
35    ov::Output<Node> image = context.get_input(1);
36    const ov::Shape kernel_shape = context.get_input(0).get_shape();
37
38    const size_t IC = is_2D ? kernel_shape[1] : kernel_shape[2];
39    const size_t KH = is_2D ? kernel_shape[2] : 1;
40    const size_t KW = kernel_shape[3];
41
42    int32_t stride_w = s0;
43    int32_t stride_h = is_2D ? s1 : 1;
44    int32_t pad_w = p0;
45    int32_t pad_h = is_2D ? p1 : 0;
46    int32_t dil_w = d0;
47    int32_t dil_h = is_2D ? d1 : 1;
48
49    if (!is_2D) {
50        // GGML input shape: [IW, IC, N, 1]
51        // OpenVINO input shape: [1, N, IC, IW]
52        // Reshape image to: [N, IC, 1, IW]
53        const ov::Shape image_shape = image.get_shape();
54        const size_t N = image_shape[1];
55        const size_t IW = image_shape[3];
56        auto image_reshape_shape = ov::op::v0::Constant::create(
57            ov::element::i64, ov::Shape{4},
58            std::vector<int64_t>{static_cast<int64_t>(N), static_cast<int64_t>(IC), 1, static_cast<int64_t>(IW)});
59        image = std::make_shared<ov::op::v1::Reshape>(image, image_reshape_shape, false);
60    }
61
62    const ov::Shape patch_sizes = {KH, KW};
63    const ov::Strides strides = {static_cast<size_t>(stride_h), static_cast<size_t>(stride_w)};
64    const ov::Shape rates = {static_cast<size_t>(dil_h), static_cast<size_t>(dil_w)};
65
66    auto pads_begin =
67        ov::op::v0::Constant::create(ov::element::i64, ov::Shape{4}, std::vector<int64_t>{0, 0, pad_h, pad_w});
68    auto pads_end =
69        ov::op::v0::Constant::create(ov::element::i64, ov::Shape{4}, std::vector<int64_t>{0, 0, pad_h, pad_w});
70
71    auto pad = std::make_shared<ov::op::v1::Pad>(image, pads_begin, pads_end, ov::op::PadMode::CONSTANT);
72    auto patches =
73        std::make_shared<ov::op::v3::ExtractImagePatches>(pad, patch_sizes, strides, rates, ov::op::PadType::VALID);
74
75    // [N, KH*KW*IC, OH, OW] → [N, OH, OW, KH*KW*IC]
76    auto perm1 = ov::op::v0::Constant::create(ov::element::i64, ov::Shape{4}, std::vector<int64_t>{0, 2, 3, 1});
77    auto t1 = std::make_shared<ov::op::v1::Transpose>(patches, perm1);
78
79    // [N, OH, OW, KH*KW*IC] → [N, OH, OW, KH*KW, IC]
80    const ov::Shape out_shape = t1->get_output_shape(0);
81    const size_t N = out_shape[0];
82    const size_t OH = out_shape[1];
83    const size_t OW = out_shape[2];
84    auto reshape1_shape = ov::op::v0::Constant::create(
85        ov::element::i64, ov::Shape{5},
86        std::vector<int64_t>{static_cast<int64_t>(N), static_cast<int64_t>(OH), static_cast<int64_t>(OW),
87                             static_cast<int64_t>(KH * KW), static_cast<int64_t>(IC)});
88    auto r1 = std::make_shared<ov::op::v1::Reshape>(t1, reshape1_shape, false);
89
90    // [N, OH, OW, KH*KW, IC] → [N, OH, OW, IC, KH*KW]
91    auto perm2 = ov::op::v0::Constant::create(ov::element::i64, ov::Shape{5}, std::vector<int64_t>{0, 1, 2, 4, 3});
92    auto t2 = std::make_shared<ov::op::v1::Transpose>(r1, perm2);
93
94    // flatten back to [N, OH, OW, IC*KH*KW]
95    auto r2_shape = ov::op::v0::Constant::create(
96        ov::element::i64, ov::Shape{4},
97        std::vector<int64_t>{static_cast<int64_t>(N), static_cast<int64_t>(OH), static_cast<int64_t>(OW),
98                             static_cast<int64_t>(IC * KH * KW)});
99    res = std::make_shared<ov::op::v1::Reshape>(t2, r2_shape, false);
100
101    if (!is_2D) {
102        // [N, 1, OW, IC * KW] -> [1, N, OW, IC * KW]
103        auto final_reshape_shape = ov::op::v0::Constant::create(
104            ov::element::i64, ov::Shape{4},
105            std::vector<int64_t>{1, static_cast<int64_t>(N), static_cast<int64_t>(OW), static_cast<int64_t>(IC * KW)});
106        res = std::make_shared<ov::op::v1::Reshape>(res, final_reshape_shape, false);
107    }
108
109    auto output_type = context.get_output_type();
110    if (res.get_element_type() != output_type) {
111        res = std::make_shared<ov::op::v0::Convert>(res, output_type);
112    }
113
114    return rename_outputs_with_suffix({res}, context.get_name());
115}
116
117}  // namespace op
118}  // namespace ggml
119}  // namespace frontend
120}  // namespace ov