forked from openvinotoolkit/openvino
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathread_paddle_model_test.cpp
More file actions
324 lines (282 loc) · 14.5 KB
/
Copy pathread_paddle_model_test.cpp
File metadata and controls
324 lines (282 loc) · 14.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// Copyright (C) 2018-2026 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include <fstream>
#include <limits>
#include <openvino/util/file_util.hpp>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include "common_test_utils/ov_test_utils.hpp"
#include "common_test_utils/unicode_utils.hpp"
#include "frontend/shared/include/utils.hpp"
#include "openvino/frontend/manager.hpp"
#include "openvino/openvino.hpp"
#include "openvino/opsets/opset1.hpp"
#include "openvino/opsets/opset8.hpp"
#include "openvino/pass/serialize.hpp"
namespace {
void append_varint(std::string& out, uint64_t value) {
while (value > 0x7F) {
out.push_back(static_cast<char>((value & 0x7F) | 0x80));
value >>= 7;
}
out.push_back(static_cast<char>(value));
}
void append_key(std::string& out, uint32_t field_number, uint8_t wire_type) {
append_varint(out, (static_cast<uint64_t>(field_number) << 3) | wire_type);
}
std::string make_tensor_desc_bytes(const std::vector<int64_t>& dims, int32_t data_type) {
std::string out;
append_key(out, 1, 0);
append_varint(out, static_cast<uint64_t>(data_type));
for (const auto& dim : dims) {
append_key(out, 2, 0);
append_varint(out, static_cast<uint64_t>(dim));
}
return out;
}
std::string make_weights_with_tensor_desc(const std::string& desc_bytes) {
std::string out;
out.reserve(16 + sizeof(int32_t) + desc_bytes.size());
out.append(16, '\0');
int32_t desc_size = static_cast<int32_t>(desc_bytes.size());
out.append(reinterpret_cast<const char*>(&desc_size), sizeof(desc_size));
out.append(desc_bytes);
return out;
}
std::string make_invalid_weights_with_bad_desc_size() {
constexpr int32_t kMaxTensorDescSize = 64 * 1024 * 1024;
std::string out;
out.reserve(16 + sizeof(int32_t));
out.append(16, '\0');
int32_t desc_size = kMaxTensorDescSize + 1;
out.append(reinterpret_cast<const char*>(&desc_size), sizeof(desc_size));
return out;
}
} // namespace
TEST(Paddle_Reader_Tests, LoadModelMemoryToCore) {
auto model = FrontEndTestUtils::make_model_path(std::string(TEST_PADDLE_MODELS_DIRNAME) +
"conv2d_relu/conv2d_relu" + std::string(TEST_PADDLE_MODEL_EXT));
auto param = FrontEndTestUtils::make_model_path(std::string(TEST_PADDLE_MODELS_DIRNAME) +
"conv2d_relu/conv2d_relu.pdiparams");
ov::Core core;
auto read_file = [&](const std::string& file_name, size_t& size) {
FILE* sFile = fopen(file_name.c_str(), "r");
if (sFile == nullptr) {
return (uint8_t*)nullptr;
}
fseek(sFile, 0, SEEK_END);
size = ftell(sFile);
uint8_t* ss = (uint8_t*)malloc(size);
rewind(sFile);
const size_t length = fread(&ss[0], 1, size, sFile);
if (size != length) {
std::cerr << "file size is not correct\n";
}
fclose(sFile);
return ss;
};
size_t xml_size, bin_size;
auto xml_ptr = read_file(model, xml_size);
ASSERT_TRUE(xml_ptr != nullptr) << "can't open " << model;
auto bin_ptr = read_file(param, bin_size);
ASSERT_TRUE(bin_ptr != nullptr) << "can't open " << param;
ov::Tensor weight_tensor = ov::Tensor(ov::element::u8, {1, bin_size}, bin_ptr);
std::string model_str = std::string((char*)xml_ptr, xml_size);
auto function = core.read_model(model_str, weight_tensor);
const auto inputType = ov::element::f32;
const auto inputShape = ov::Shape{1, 3, 4, 4};
const auto data = std::make_shared<ov::opset1::Parameter>(inputType, inputShape);
data->set_friendly_name("xxx");
data->output(0).get_tensor().add_names({"xxx"});
const auto weight = std::make_shared<ov::opset1::Constant>(ov::element::f32, ov::Shape{5, 3, 1, 1}, 1.0);
const auto conv2d = std::make_shared<ov::opset1::Convolution>(data->output(0),
weight->output(0),
ov::Strides({1, 1}),
ov::CoordinateDiff({1, 1}),
ov::CoordinateDiff({1, 1}),
ov::Strides({1, 1}));
conv2d->set_friendly_name("conv2d_0.tmp_0");
conv2d->output(0).get_tensor().add_names({"conv2d_0.tmp_0"});
const auto relu = std::make_shared<ov::opset1::Relu>(conv2d->output(0));
relu->set_friendly_name("relu_0.tmp_0");
relu->output(0).get_tensor().add_names({"relu_0.tmp_0"});
std::shared_ptr<ov::opset1::Result> result;
if (std::string(TEST_GEN_TAG) == "ge3") {
result = std::make_shared<ov::opset1::Result>(relu->output(0));
result->set_friendly_name("save_infer_model/scale_0.tmp_0");
} else if (std::string(TEST_GEN_TAG) == "ge2") {
const auto bias = std::make_shared<ov::opset1::Constant>(ov::element::f32, ov::Shape{}, 0.0);
const auto scale = std::make_shared<ov::opset1::Constant>(ov::element::f32, ov::Shape{}, 1.0);
const auto mul = std::make_shared<ov::opset1::Multiply>(relu->output(0), scale);
const auto add = std::make_shared<ov::opset1::Add>(mul->output(0), bias);
add->set_friendly_name("scale_0.tmp_0");
add->output(0).get_tensor().add_names({"save_infer_model/scale_0.tmp_0"});
result = std::make_shared<ov::opset1::Result>(add->output(0));
result->set_friendly_name("save_infer_model/scale_0.tmp_0/Result");
} else {
ASSERT_TRUE(false) << "Unsupported TEST_GEN_TAG: " << std::string(TEST_GEN_TAG);
}
const auto reference = std::make_shared<ov::Model>(ov::OutputVector{result}, ov::ParameterVector{data}, "Model0");
const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::NONE);
const FunctionsComparator::Result res = func_comparator(function, reference);
ASSERT_TRUE(res.valid) << res.message;
free(xml_ptr);
free(bin_ptr);
}
TEST(Paddle_Reader_Tests, ImportBasicModelToCore) {
auto model = FrontEndTestUtils::make_model_path(std::string(TEST_PADDLE_MODELS_DIRNAME) + "relu/relu" +
std::string(TEST_PADDLE_MODEL_EXT));
ov::Core core;
auto function = core.read_model(FrontEndTestUtils::make_model_path(model));
const auto inputType = ov::element::f32;
const auto inputShape = ov::Shape{3};
const auto data = std::make_shared<ov::opset1::Parameter>(inputType, inputShape);
data->set_friendly_name("x");
data->output(0).get_tensor().add_names({"x"});
const auto relu = std::make_shared<ov::opset1::Relu>(data->output(0));
relu->set_friendly_name("relu_0.tmp_0");
relu->output(0).get_tensor().add_names({"relu_0.tmp_0"});
std::shared_ptr<ov::opset1::Result> result;
if (std::string(TEST_GEN_TAG) == "ge3") {
result = std::make_shared<ov::opset1::Result>(relu->output(0));
result->set_friendly_name("save_infer_model/scale_0.tmp_0");
} else if (std::string(TEST_GEN_TAG) == "ge2") {
const auto bias = std::make_shared<ov::opset1::Constant>(ov::element::f32, ov::Shape{}, 0.0);
const auto scale = std::make_shared<ov::opset1::Constant>(ov::element::f32, ov::Shape{}, 1.0);
const auto mul = std::make_shared<ov::opset1::Multiply>(relu->output(0), scale);
const auto add = std::make_shared<ov::opset1::Add>(mul->output(0), bias);
add->set_friendly_name("save_infer_model/scale_0.tmp_0");
add->output(0).get_tensor().add_names({"save_infer_model/scale_0.tmp_0"});
result = std::make_shared<ov::opset1::Result>(add->output(0));
result->set_friendly_name("save_infer_model/scale_0.tmp_0/Result");
} else {
ASSERT_TRUE(false) << "Unsupported TEST_GEN_TAG: " << std::string(TEST_GEN_TAG);
}
const auto reference = std::make_shared<ov::Model>(ov::OutputVector{result}, ov::ParameterVector{data}, "Model0");
const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::NAMES);
const FunctionsComparator::Result res = func_comparator(function, reference);
ASSERT_TRUE(res.valid) << res.message;
}
TEST(Paddle_Reader_Tests, LoadModelWithInvalidTensorDescSize) {
auto model_path = FrontEndTestUtils::make_model_path(
std::string(TEST_PADDLE_MODELS_DIRNAME) + "conv2d_relu/conv2d_relu" + std::string(TEST_PADDLE_MODEL_EXT));
std::ifstream model_ifs(model_path, std::ios::in | std::ios::binary);
ASSERT_TRUE(model_ifs.is_open()) << "Cannot open model file: " << model_path;
const auto weights_bytes = make_invalid_weights_with_bad_desc_size();
std::istringstream weights_is(weights_bytes, std::ios::in | std::ios::binary);
auto fem = ov::frontend::FrontEndManager();
std::istream* model_stream = &model_ifs;
std::istream* weights_stream = &weights_is;
auto fe = fem.load_by_model(model_stream, weights_stream);
ASSERT_NE(fe, nullptr);
model_ifs.clear();
model_ifs.seekg(0, std::ios::beg);
weights_is.clear();
weights_is.seekg(0, std::ios::beg);
try {
fe->load(model_stream, weights_stream);
FAIL() << "Expected load to fail due to invalid TensorDesc size";
} catch (const std::exception& ex) {
const std::string msg = ex.what();
ASSERT_NE(msg.find("TensorDesc size is invalid"), std::string::npos) << msg;
}
}
TEST(Paddle_Reader_Tests, LoadModelWithNegativeDimInTensorDesc) {
auto model_path = FrontEndTestUtils::make_model_path(
std::string(TEST_PADDLE_MODELS_DIRNAME) + "conv2d_relu/conv2d_relu" + std::string(TEST_PADDLE_MODEL_EXT));
std::ifstream model_ifs(model_path, std::ios::in | std::ios::binary);
ASSERT_TRUE(model_ifs.is_open()) << "Cannot open model file: " << model_path;
const auto desc_bytes = make_tensor_desc_bytes({-1}, 5);
const auto weights_bytes = make_weights_with_tensor_desc(desc_bytes);
std::istringstream weights_is(weights_bytes, std::ios::in | std::ios::binary);
auto fem = ov::frontend::FrontEndManager();
std::istream* model_stream = &model_ifs;
std::istream* weights_stream = &weights_is;
auto fe = fem.load_by_model(model_stream, weights_stream);
ASSERT_NE(fe, nullptr);
model_ifs.clear();
model_ifs.seekg(0, std::ios::beg);
weights_is.clear();
weights_is.seekg(0, std::ios::beg);
try {
fe->load(model_stream, weights_stream);
FAIL() << "Expected load to fail due to negative dimension";
} catch (const std::exception& ex) {
const std::string msg = ex.what();
ASSERT_NE(msg.find("Negative dimension in Paddle weight tensor"), std::string::npos) << msg;
}
}
TEST(Paddle_Reader_Tests, LoadModelWithOverflowingTensorSize) {
auto model_path = FrontEndTestUtils::make_model_path(
std::string(TEST_PADDLE_MODELS_DIRNAME) + "conv2d_relu/conv2d_relu" + std::string(TEST_PADDLE_MODEL_EXT));
std::ifstream model_ifs(model_path, std::ios::in | std::ios::binary);
ASSERT_TRUE(model_ifs.is_open()) << "Cannot open model file: " << model_path;
const auto desc_bytes = make_tensor_desc_bytes({std::numeric_limits<int64_t>::max(), 2}, 5);
const auto weights_bytes = make_weights_with_tensor_desc(desc_bytes);
std::istringstream weights_is(weights_bytes, std::ios::in | std::ios::binary);
auto fem = ov::frontend::FrontEndManager();
std::istream* model_stream = &model_ifs;
std::istream* weights_stream = &weights_is;
auto fe = fem.load_by_model(model_stream, weights_stream);
ASSERT_NE(fe, nullptr);
model_ifs.clear();
model_ifs.seekg(0, std::ios::beg);
weights_is.clear();
weights_is.seekg(0, std::ios::beg);
try {
fe->load(model_stream, weights_stream);
FAIL() << "Expected load to fail due to overflowing tensor size";
} catch (const std::exception& ex) {
const std::string msg = ex.what();
const bool has_weight_overflow = msg.find("Weight tensor size overflow for constant") != std::string::npos;
const bool has_dim_overflow =
msg.find("Dimension is too large for size_t in Paddle weight tensor.") != std::string::npos;
ASSERT_TRUE(has_weight_overflow || has_dim_overflow) << msg;
}
}
#if defined(OPENVINO_ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32)
TEST(Paddle_Reader_Tests, ImportBasicModelToCoreWstring) {
std::string win_dir_path{TEST_PADDLE_MODELS_DIRNAME "relu/relu" + std::string(TEST_PADDLE_MODEL_EXT)};
win_dir_path = FrontEndTestUtils::make_model_path(win_dir_path);
std::wstring wmodel =
ov::test::utils::addUnicodePostfixToPath(win_dir_path, ov::test::utils::test_unicode_postfix_vector[0]);
bool is_copy_successfully = ov::test::utils::copyFile(win_dir_path, wmodel);
if (!is_copy_successfully) {
FAIL() << "Unable to copy from '" << win_dir_path << "' to '" << ov::util::wstring_to_string(wmodel) << "'";
}
ov::Core core;
auto function = core.read_model(wmodel);
ov::test::utils::removeFile(wmodel);
const auto inputType = ov::element::f32;
const auto inputShape = ov::Shape{3};
const auto data = std::make_shared<ov::opset1::Parameter>(inputType, inputShape);
data->set_friendly_name("x");
data->output(0).get_tensor().add_names({"x"});
const auto relu = std::make_shared<ov::opset1::Relu>(data->output(0));
relu->set_friendly_name("relu_0.tmp_0");
relu->output(0).get_tensor().add_names({"relu_0.tmp_0"});
const auto result = std::make_shared<ov::opset1::Result>(relu->output(0));
result->set_friendly_name("relu_0.tmp_0/Result");
const auto reference = std::make_shared<ov::Model>(ov::OutputVector{result}, ov::ParameterVector{data}, "Model0");
const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::NAMES);
const FunctionsComparator::Result res = func_comparator(function, reference);
ASSERT_TRUE(res.valid) << res.message;
}
#endif
TEST(Paddle_Reader_Tests, LoadModelWithPartialOpsInsufficientInputs) {
auto model =
FrontEndTestUtils::make_model_path(std::string(TEST_PADDLE_MODELS_DIRNAME) + "partial_sum_oob/partial_sum_oob" +
std::string(TEST_PADDLE_MODEL_EXT));
ov::Core core;
try {
core.read_model(model);
FAIL() << "Expected load to fail due to insufficient X inputs for partial_sum";
} catch (const std::exception& ex) {
const std::string msg = ex.what();
ASSERT_NE(msg.find("partial_ops requires exactly 2 inputs in X."), std::string::npos) << msg;
}
}