Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/gapi/test/internal/gapi_int_island_fusion_tests.cpp
16339 views
1
// This file is part of OpenCV project.
2
// It is subject to the license terms in the LICENSE file found in the top-level directory
3
// of this distribution and at http://opencv.org/license.html.
4
//
5
// Copyright (C) 2018 Intel Corporation
6
7
8
#include "test_precomp.hpp"
9
#include "compiler/transactions.hpp"
10
11
#include "gapi_mock_kernels.hpp"
12
13
#include "compiler/gmodel.hpp"
14
#include "compiler/gislandmodel.hpp"
15
#include "compiler/gcompiler.hpp"
16
17
namespace opencv_test
18
{
19
20
TEST(IslandFusion, TwoOps_OneIsland)
21
{
22
namespace J = Jupiter; // see mock_kernels.cpp
23
24
// Define a computation:
25
//
26
// (in) -> J::Foo1 -> (tmp0) -> J::Foo2 -> (out)
27
// : :
28
// : "island0" :
29
// :<----------------------------->:
30
31
cv::GMat in;
32
cv::GMat tmp0 = I::Foo::on(in);
33
cv::GMat out = I::Foo::on(tmp0);
34
cv::GComputation cc(in, out);
35
36
// Prepare compilation parameters manually
37
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
38
const auto pkg = cv::gapi::kernels<J::Foo>();
39
40
// Directly instantiate G-API graph compiler and run partial compilation
41
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
42
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
43
compiler.runPasses(*graph);
44
45
// Inspect the graph and verify the islands configuration
46
cv::gimpl::GModel::ConstGraph gm(*graph);
47
48
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
49
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
50
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
51
52
// in/out mats shouldn't be assigned to any Island
53
EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
54
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
55
56
// Since tmp is surrounded by two J kernels, tmp should be assigned
57
// to island J
58
EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
59
}
60
61
TEST(IslandFusion, TwoOps_TwoIslands)
62
{
63
namespace J = Jupiter; // see mock_kernels.cpp
64
namespace S = Saturn; // see mock_kernels.cpp
65
66
// Define a computation:
67
//
68
// (in) -> J::Foo --> (tmp0) -> S::Bar --> (out)
69
// : : -> :
70
// : : : :
71
// :<-------->: :<-------->:
72
73
cv::GMat in;
74
cv::GMat tmp0 = I::Foo::on(in);
75
cv::GMat out = I::Bar::on(tmp0, tmp0);
76
cv::GComputation cc(in, out);
77
78
// Prepare compilation parameters manually
79
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
80
const auto pkg = cv::gapi::kernels<J::Foo, S::Bar>();
81
82
// Directly instantiate G-API graph compiler and run partial compilation
83
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
84
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
85
compiler.runPasses(*graph);
86
87
// Inspect the graph and verify the islands configuration
88
cv::gimpl::GModel::ConstGraph gm(*graph);
89
90
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
91
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
92
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
93
94
// in/tmp/out mats shouldn't be assigned to any Island
95
EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
96
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
97
EXPECT_FALSE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
98
99
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
100
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
101
102
// There should be two islands in the GIslandModel
103
const auto is_island = [&](ade::NodeHandle nh) {
104
return (cv::gimpl::NodeKind::ISLAND
105
== gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
106
};
107
const std::size_t num_isl = std::count_if(gim.nodes().begin(),
108
gim.nodes().end(),
109
is_island);
110
EXPECT_EQ(2u, num_isl);
111
112
auto isl_foo_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
113
auto isl_bar_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
114
ASSERT_NE(nullptr, isl_foo_nh);
115
ASSERT_NE(nullptr, isl_bar_nh);
116
117
// Islands should be different
118
auto isl_foo_obj = gim.metadata(isl_foo_nh).get<cv::gimpl::FusedIsland>().object;
119
auto isl_bar_obj = gim.metadata(isl_bar_nh).get<cv::gimpl::FusedIsland>().object;
120
EXPECT_FALSE(isl_foo_obj == isl_bar_obj);
121
}
122
123
TEST(IslandFusion, ConsumerHasTwoInputs)
124
{
125
namespace J = Jupiter; // see mock_kernels.cpp
126
127
// Define a computation: island
128
// ............................
129
// (in0) ->:J::Foo -> (tmp) -> S::Bar :--> (out)
130
// :....................^.....:
131
// |
132
// (in1) -----------------------`
133
//
134
135
// Check that island is build correctly, when consumer has two inputs
136
137
GMat in[2];
138
GMat tmp = I::Foo::on(in[0]);
139
GMat out = I::Bar::on(tmp, in[1]);
140
141
cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
142
143
// Prepare compilation parameters manually
144
cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
145
GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
146
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
147
148
// Directly instantiate G-API graph compiler and run partial compilation
149
cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
150
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
151
compiler.runPasses(*graph);
152
153
cv::gimpl::GModel::ConstGraph gm(*graph);
154
155
auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
156
auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
157
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
158
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
159
160
EXPECT_FALSE(gm.metadata(in0_nh ).contains<cv::gimpl::Island>());
161
EXPECT_FALSE(gm.metadata(in1_nh ).contains<cv::gimpl::Island>());
162
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
163
EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
164
165
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
166
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
167
168
const auto is_island = [&](ade::NodeHandle nh) {
169
return (cv::gimpl::NodeKind::ISLAND
170
== gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
171
};
172
const std::size_t num_isl = std::count_if(gim.nodes().begin(),
173
gim.nodes().end(),
174
is_island);
175
EXPECT_EQ(1u, num_isl);
176
177
auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
178
auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
179
180
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp_nh));
181
182
EXPECT_EQ(2u, static_cast<std::size_t>(isl_nh->inNodes().size()));
183
EXPECT_EQ(1u, static_cast<std::size_t>(isl_nh->outNodes().size()));
184
}
185
186
TEST(IslandFusion, DataNodeUsedDifferentBackend)
187
{
188
// Define a computation:
189
//
190
// internal isl isl0
191
// ...........................
192
// (in1) -> :J::Foo--> (tmp) -> J::Foo: --> (out0)
193
// :............|............:
194
// | ........
195
// `---->:S::Baz: --> (out1)
196
// :......:
197
198
// Check that the node was not dropped out of the island
199
// because it is used by the kernel from another backend
200
201
namespace J = Jupiter;
202
namespace S = Saturn;
203
204
cv::GMat in, tmp, out0;
205
cv::GScalar out1;
206
tmp = I::Foo::on(in);
207
out0 = I::Foo::on(tmp);
208
out1 = I::Baz::on(tmp);
209
210
cv::GComputation cc(cv::GIn(in), cv::GOut(out0, out1));
211
212
// Prepare compilation parameters manually
213
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
214
const auto pkg = cv::gapi::kernels<J::Foo, S::Baz>();
215
216
// Directly instantiate G-API graph compiler and run partial compilation
217
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
218
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
219
compiler.runPasses(*graph);
220
221
// Inspect the graph and verify the islands configuration
222
cv::gimpl::GModel::ConstGraph gm(*graph);
223
224
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
225
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
226
auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out0);
227
auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out1);
228
229
EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
230
231
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
232
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
233
234
auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
235
auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
236
237
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp_nh));
238
239
EXPECT_EQ(2u, static_cast<std::size_t>(isl_nh->outNodes().size()));
240
EXPECT_EQ(7u, static_cast<std::size_t>(gm.nodes().size()));
241
EXPECT_EQ(6u, static_cast<std::size_t>(gim.nodes().size()));
242
}
243
244
TEST(IslandFusion, LoopBetweenDifferentBackends)
245
{
246
// Define a computation:
247
//
248
//
249
// .............................
250
// (in) -> :J::Baz -> (tmp0) -> J::Quux: -> (out0)
251
// | :............|..........^....
252
// | ........ | | ........
253
// `---->:S::Foo: `----------|-------->:S::Qux:-> (out1)
254
// :....|.: | :....^.:
255
// | | |
256
// `-------------- (tmp1) -----------`
257
258
// Kernels S::Foo and S::Qux cannot merge, because there will be a cycle between islands
259
260
namespace J = Jupiter;
261
namespace S = Saturn;
262
263
cv::GScalar tmp0;
264
cv::GMat in, tmp1, out0, out1;
265
266
tmp0 = I::Baz::on(in);
267
tmp1 = I::Foo::on(in);
268
out1 = I::Qux::on(tmp1, tmp0);
269
out0 = I::Quux::on(tmp0, tmp1);
270
271
cv::GComputation cc(cv::GIn(in), cv::GOut(out1, out0));
272
273
// Prepare compilation parameters manually
274
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
275
const auto pkg = cv::gapi::kernels<J::Baz, J::Quux, S::Foo, S::Qux>();
276
277
// Directly instantiate G-API graph compiler and run partial compilation
278
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
279
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
280
compiler.runPasses(*graph);
281
282
cv::gimpl::GModel::ConstGraph gm(*graph);
283
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
284
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
285
286
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
287
auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
288
auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp1);
289
auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out0);
290
auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out1);
291
292
EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
293
EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
294
EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
295
// The node does not belong to the island so as not to form a cycle
296
EXPECT_FALSE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
297
298
EXPECT_TRUE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
299
300
// There should be three islands in the GIslandModel
301
const auto is_island = [&](ade::NodeHandle nh) {
302
return (cv::gimpl::NodeKind::ISLAND
303
== gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
304
};
305
const std::size_t num_isl = std::count_if(gim.nodes().begin(),
306
gim.nodes().end(),
307
is_island);
308
EXPECT_EQ(3u, num_isl);
309
}
310
311
TEST(IslandsFusion, PartionOverlapUserIsland)
312
{
313
// Define a computation:
314
//
315
// internal isl isl0
316
// ........ ........
317
// (in0) -> :J::Foo:--> (tmp) ->:S::Bar: --> (out)
318
// :......: :......:
319
// ^
320
// |
321
// (in1) --------------------------`
322
323
// Check that internal islands does't overlap user island
324
325
namespace J = Jupiter;
326
namespace S = Saturn;
327
328
GMat in[2];
329
GMat tmp = I::Foo::on(in[0]);
330
GMat out = I::Bar::on(tmp, in[1]);
331
332
cv::gapi::island("isl0", cv::GIn(tmp, in[1]), cv::GOut(out));
333
cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
334
335
// Prepare compilation parameters manually
336
cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
337
GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
338
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
339
340
// Directly instantiate G-API graph compiler and run partial compilation
341
cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
342
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
343
compiler.runPasses(*graph);
344
345
cv::gimpl::GModel::ConstGraph gm(*graph);
346
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
347
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
348
349
auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
350
auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
351
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
352
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
353
354
auto foo_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
355
auto foo_obj = gim.metadata(foo_nh).get<cv::gimpl::FusedIsland>().object;
356
357
auto bar_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
358
auto bar_obj = gim.metadata(bar_nh).get<cv::gimpl::FusedIsland>().object;
359
360
EXPECT_FALSE(gm.metadata(in0_nh ).contains<cv::gimpl::Island>());
361
EXPECT_FALSE(gm.metadata(in1_nh ).contains<cv::gimpl::Island>());
362
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
363
EXPECT_FALSE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
364
EXPECT_FALSE(foo_obj->is_user_specified());
365
EXPECT_TRUE(bar_obj->is_user_specified());
366
}
367
368
TEST(IslandsFusion, DISABLED_IslandContainsDifferentBackends)
369
{
370
// Define a computation:
371
//
372
// isl0
373
// ............................
374
// (in0) -> :J::Foo:--> (tmp) -> S::Bar: --> (out)
375
// :..........................:
376
// ^
377
// |
378
// (in1) --------------------------`
379
380
// Try create island contains different backends
381
382
namespace J = Jupiter;
383
namespace S = Saturn;
384
385
GMat in[2];
386
GMat tmp = I::Foo::on(in[0]);
387
GMat out = I::Bar::on(tmp, in[1]);
388
389
cv::gapi::island("isl0", cv::GIn(in[0], in[1]), cv::GOut(out));
390
cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
391
392
// Prepare compilation parameters manually
393
cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
394
GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
395
const auto pkg = cv::gapi::kernels<J::Foo, S::Bar>();
396
397
// Directly instantiate G-API graph compiler and run partial compilation
398
cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
399
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
400
EXPECT_ANY_THROW(compiler.runPasses(*graph));
401
}
402
403
TEST(IslandFusion, WithLoop)
404
{
405
namespace J = Jupiter; // see mock_kernels.cpp
406
407
// Define a computation:
408
//
409
// (in) -> J::Foo --> (tmp0) -> J::Foo --> (tmp1) -> J::Qux -> (out)
410
// : ^
411
// '--> J::Baz --> (scl0) --'
412
//
413
// The whole thing should be merged to a single island
414
// There's a cycle warning if Foo/Foo/Qux are merged first
415
// Then this island both produces data for Baz and consumes data
416
// from Baz. This is a cycle and it should be avoided by the merging code.
417
//
418
cv::GMat in;
419
cv::GMat tmp0 = I::Foo::on(in);
420
cv::GMat tmp1 = I::Foo::on(tmp0);
421
cv::GScalar scl0 = I::Baz::on(tmp0);
422
cv::GMat out = I::Qux::on(tmp1, scl0);
423
cv::GComputation cc(in, out);
424
425
// Prepare compilation parameters manually
426
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
427
const auto pkg = cv::gapi::kernels<J::Foo, J::Baz, J::Qux>();
428
429
// Directly instantiate G-API graph compiler and run partial compilation
430
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
431
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
432
compiler.runPasses(*graph);
433
434
// Inspect the graph and verify the islands configuration
435
cv::gimpl::GModel::ConstGraph gm(*graph);
436
437
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
438
auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
439
auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp1);
440
auto scl0_nh = cv::gimpl::GModel::dataNodeOf(gm, scl0);
441
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
442
443
// in/out mats shouldn't be assigned to any Island
444
EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
445
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
446
447
// tmp0/tmp1/scl should be assigned to island
448
EXPECT_TRUE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
449
EXPECT_TRUE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
450
EXPECT_TRUE(gm.metadata(scl0_nh).contains<cv::gimpl::Island>());
451
452
// Check that there's a single island object and it contains all
453
// that data object handles
454
455
cv::gimpl::GModel::ConstGraph cg(*graph);
456
auto isl_model = cg.metadata().get<cv::gimpl::IslandModel>().model;
457
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
458
459
const auto is_island = [&](ade::NodeHandle nh) {
460
return (cv::gimpl::NodeKind::ISLAND
461
== gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
462
};
463
const std::size_t num_isl = std::count_if(gim.nodes().begin(),
464
gim.nodes().end(),
465
is_island);
466
EXPECT_EQ(1u, num_isl);
467
468
auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
469
auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
470
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp0_nh));
471
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp1_nh));
472
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), scl0_nh));
473
}
474
475
TEST(IslandFusion, Regression_ShouldFuseAll)
476
{
477
// Initially the merge procedure didn't work as expected and
478
// stopped fusion even if it could be continued (e.g. full
479
// GModel graph could be fused into a single GIsland node).
480
// Example of this is custom RGB 2 YUV pipeline as shown below:
481
482
cv::GMat r, g, b;
483
cv::GMat y = 0.299f*r + 0.587f*g + 0.114f*b;
484
cv::GMat u = 0.492f*(b - y);
485
cv::GMat v = 0.877f*(r - y);
486
487
cv::GComputation customCvt({r, g, b}, {y, u, v});
488
489
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
490
491
// Directly instantiate G-API graph compiler and run partial compilation
492
cv::gimpl::GCompiler compiler(customCvt, {in_meta,in_meta,in_meta}, cv::compile_args());
493
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
494
compiler.runPasses(*graph);
495
496
cv::gimpl::GModel::ConstGraph cg(*graph);
497
auto isl_model = cg.metadata().get<cv::gimpl::IslandModel>().model;
498
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
499
500
std::vector<ade::NodeHandle> data_nhs;
501
std::vector<ade::NodeHandle> isl_nhs;
502
for (auto &&nh : gim.nodes())
503
{
504
if (gim.metadata(nh).contains<cv::gimpl::FusedIsland>())
505
isl_nhs.push_back(std::move(nh));
506
else if (gim.metadata(nh).contains<cv::gimpl::DataSlot>())
507
data_nhs.push_back(std::move(nh));
508
else FAIL() << "GIslandModel node with unexpected metadata type";
509
}
510
511
EXPECT_EQ(6u, data_nhs.size()); // 3 input nodes + 3 output nodes
512
EXPECT_EQ(1u, isl_nhs.size()); // 1 island
513
}
514
515
// FIXME: add more tests on mixed (hetero) graphs
516
// ADE-222, ADE-223
517
518
// FIXME: add test on combination of user-specified island
519
// which should be heterogeneous (based on kernel availability)
520
// but as we don't support this, compilation should fail
521
522
// FIXME: add tests on automatic inferred islands which are
523
// connected via 1) gmat 2) gscalar 3) garray,
524
// check the case with executor
525
// check the case when this 1/2/3 interim object is also gcomputation output
526
527
} // namespace opencv_test
528
529