1 | /******************************************************************************* |
2 | * Copyright 2019-2022 Intel Corporation |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | *******************************************************************************/ |
16 | |
17 | #include <cstring> |
18 | #include <memory> |
19 | #include <tuple> |
20 | |
21 | #include "dnnl_test_common.hpp" |
22 | #include "gtest/gtest.h" |
23 | |
24 | #include "oneapi/dnnl/dnnl.hpp" |
25 | |
26 | namespace dnnl { |
27 | |
28 | using data_t = float; |
29 | |
30 | struct params_t { |
31 | memory::dims dims; |
32 | memory::format_tag fmt_tag; |
33 | dnnl_status_t expected_status; |
34 | }; |
35 | |
36 | using params_w_engine_t = std::tuple<dnnl::engine::kind, params_t>; |
37 | |
38 | class memory_creation_test_t |
39 | : public ::testing::TestWithParam<params_w_engine_t> { |
40 | protected: |
41 | void SetUp() override { |
42 | params_w_engine_t pwe |
43 | = ::testing::TestWithParam<decltype(pwe)>::GetParam(); |
44 | |
45 | auto engine_kind = std::get<0>(pwe); |
46 | if (dnnl::engine::get_count(engine_kind) == 0) return; |
47 | |
48 | eng = dnnl::engine(engine_kind, 0); |
49 | p = std::get<1>(pwe); |
50 | } |
51 | |
52 | void Test() { |
53 | dnnl::memory::desc md(p.dims, memory::data_type::f32, p.fmt_tag); |
54 | dnnl::memory::dim phys_size = md.get_size() / sizeof(data_t); |
55 | |
56 | #ifdef DNNL_SYCL_CUDA |
57 | const dnnl::impl::memory_desc_wrapper mdw(md.get()); |
58 | SKIP_IF(!mdw.is_plain() && !mdw.format_any(), |
59 | "Non-plain formats are not supported on CUDA backend" ); |
60 | #endif |
61 | |
62 | // mem0 |
63 | // Initially spoiled by putting non-zero values in padded area. |
64 | auto mem0 = test::make_memory(md, eng); |
65 | |
66 | // `runtime`-aware buffer for future mem1 |
67 | auto mem1_placeholder = test::make_memory(md, eng); |
68 | |
69 | // Map-unmap section |
70 | { |
71 | // Put non-zeros even to the padded area |
72 | auto mem0_ptr = map_memory<data_t>(mem0); |
73 | if (phys_size) GTEST_EXPECT_NE(mem0_ptr, nullptr); |
74 | fill_data<data_t>(phys_size, mem0_ptr); |
75 | |
76 | // mem1_placeholder = copy(mem0) |
77 | auto mem1_ph_ptr = map_memory<data_t>(mem1_placeholder); |
78 | if (phys_size) GTEST_EXPECT_NE(mem1_ph_ptr, nullptr); |
79 | for (dnnl::memory::dim i = 0; i < phys_size; ++i) |
80 | mem1_ph_ptr[i] = mem0_ptr[i]; |
81 | } |
82 | |
83 | auto mem1 = test::make_memory(md, eng, nullptr); |
84 | mem1.set_data_handle(mem1_placeholder.get_data_handle()); |
85 | |
86 | // Map-unmap section |
87 | { |
88 | auto mem0_ptr = map_memory<data_t>(mem0); |
89 | if (phys_size) GTEST_EXPECT_NE(mem0_ptr, nullptr); |
90 | auto mem1_ptr = map_memory<data_t>(mem1); |
91 | if (phys_size) GTEST_EXPECT_NE(mem1_ptr, nullptr); |
92 | |
93 | // Check if mem0 == mem1 |
94 | for (dnnl::memory::dim i = 0; i < phys_size; ++i) |
95 | ASSERT_EQ(mem0_ptr[i], mem1_ptr[i]) << i; |
96 | } |
97 | } |
98 | |
99 | dnnl::engine eng; |
100 | params_t p; |
101 | }; |
102 | |
103 | TEST_P(memory_creation_test_t, TestsMemoryCreation) { |
104 | SKIP_IF(eng.get(true) == nullptr, "Engine is not supported" ); |
105 | catch_expected_failures([=]() { Test(); }, |
106 | p.expected_status != dnnl_success, p.expected_status); |
107 | } |
108 | |
109 | namespace { |
110 | auto all_engine_kinds |
111 | = ::testing::Values(dnnl::engine::kind::cpu, dnnl::engine::kind::gpu); |
112 | |
113 | using fmt = dnnl::memory::format_tag; |
114 | |
115 | auto cases_expect_to_fail = ::testing::Values( |
116 | params_t {{2, 2, -1, 1}, fmt::nchw, dnnl_invalid_arguments}, |
117 | params_t {{1, 2, 3, 4}, fmt::any, dnnl_invalid_arguments}); |
118 | |
119 | auto cases_zero_dim = ::testing::Values(params_t {{2, 0, 1, 1}, fmt::nChw16c}, |
120 | params_t {{0, 1, 0, 1}, fmt::nhwc}, params_t {{2, 1, 0, 1}, fmt::nchw}); |
121 | |
122 | auto cases_generic = ::testing::Values(params_t {{2, 15, 3, 2}, fmt::nChw16c}, |
123 | params_t {{2, 15, 3, 2, 4}, fmt::nCdhw8c}, |
124 | params_t {{2, 9, 3}, fmt::OIw8o4i}, |
125 | params_t {{2, 9, 3, 2}, fmt::OIhw8o4i}, |
126 | params_t {{2, 9, 3, 2}, fmt::OIhw8o8i}, |
127 | params_t {{2, 9, 3, 2}, fmt::OIhw8i16o2i}, |
128 | params_t {{2, 9, 3, 2}, fmt::OIhw8o16i2o}, |
129 | params_t {{2, 9, 3, 2}, fmt::OIhw16o16i}, |
130 | params_t {{2, 9, 3, 2}, fmt::OIhw16i16o}, |
131 | params_t {{2, 9, 3, 2}, fmt::OIhw4i16o4i}, |
132 | params_t {{2, 9, 3, 2}, fmt::OIhw2i8o4i}, |
133 | params_t {{2, 9, 3, 2, 4}, fmt::OIdhw8o4i}, |
134 | params_t {{2, 17, 9, 2}, fmt::gOIw8o4i}, |
135 | params_t {{2, 9, 3}, fmt::OwI16o4i}, |
136 | params_t {{2, 9, 3, 2}, fmt::OhwI16o4i}, |
137 | params_t {{2, 15, 9, 3, 2}, fmt::OdhwI16o4i}, |
138 | params_t {{2, 15, 9, 3}, fmt::gOwI16o4i}, |
139 | params_t {{2, 15, 9, 3, 2}, fmt::gOhwI16o4i}, |
140 | params_t {{3, 18, 9, 3, 2, 3}, fmt::gOdhwI16o4i}, |
141 | params_t {{3, 18, 9, 3, 2, 3}, fmt::gOIdhw4i16o4i}, |
142 | params_t {{2, 18, 8, 4, 2, 3}, fmt::gOIdhw2i8o4i}, |
143 | params_t {{1, 2, 9, 3, 3, 2}, fmt::gOIdhw4o4i}, |
144 | params_t {{2, 9, 3, 2}, fmt::OIhw16i16o4i}, |
145 | params_t {{2, 9, 3, 2}, fmt::OIhw16i16o2i}, |
146 | params_t {{2, 9, 3, 2}, fmt::OIhw16o16i2o}, |
147 | params_t {{2, 9, 4, 3, 2}, fmt::OIdhw16i16o4i}, |
148 | params_t {{2, 9, 4, 3, 2}, fmt::OIdhw16i16o2i}, |
149 | params_t {{2, 9, 4, 3, 2}, fmt::gOihw16o}, |
150 | params_t {{2, 17, 9, 3, 2}, fmt::gOIhw8o4i}, |
151 | params_t {{1, 2, 9, 3, 2}, fmt::gOIhw8o8i}, |
152 | params_t {{1, 2, 9, 3, 2}, fmt::gOIhw4o4i}, |
153 | params_t {{1, 2, 9, 3, 2}, fmt::gOIhw8i8o}, |
154 | params_t {{2, 17, 9, 3, 2}, fmt::gOIhw4i16o4i}, |
155 | params_t {{2, 17, 9, 3, 2}, fmt::gOIhw2i8o4i}, |
156 | params_t {{2, 17, 9, 3, 2, 4}, fmt::gOIdhw8o4i}, |
157 | params_t {{2, 16, 16, 3}, fmt::gOIw2i4o2i}, |
158 | params_t {{2, 8, 6, 3, 3}, fmt::gOIhw2i4o2i}, |
159 | params_t {{2, 14, 18, 3, 3, 4}, fmt::gOIdhw2i4o2i}, |
160 | params_t {{2, 16, 16, 3}, fmt::gOIw4i8o2i}, |
161 | params_t {{2, 12, 18, 3, 2}, fmt::gOIhw4i8o2i}, |
162 | params_t {{2, 10, 6, 3, 5, 3}, fmt::gOIdhw4i8o2i}, |
163 | params_t {{2, 2, 3, 4}, fmt::gOIw2o4i2o}, |
164 | params_t {{2, 18, 8, 3, 3}, fmt::gOIhw2o4i2o}, |
165 | params_t {{2, 10, 6, 6, 3, 3}, fmt::gOIdhw2o4i2o}, |
166 | params_t {{2, 2, 4, 3}, fmt::gOIw4o8i2o}, |
167 | params_t {{2, 14, 10, 3, 3}, fmt::gOIhw4o8i2o}, |
168 | params_t {{2, 8, 8, 3, 3, 3}, fmt::gOIdhw4o8i2o}, |
169 | params_t {{15, 16, 16, 3, 3}, fmt::Goihw8g}, |
170 | params_t {{2, 9, 3}, fmt::OIw2i8o4i}, |
171 | params_t {{2, 17, 9, 3}, fmt::gOIw2i8o4i}, |
172 | params_t {{15, 16, 16, 3}, fmt::Goiw8g}, |
173 | params_t {{2, 17, 9, 3, 2}, fmt::gOIhw16i16o4i}, |
174 | params_t {{2, 17, 9, 3, 2}, fmt::gOIhw16i16o2i}, |
175 | params_t {{2, 17, 9, 3, 2}, fmt::gOIhw16o16i2o}, |
176 | params_t {{2, 15, 17, 9, 3, 2}, fmt::gOIdhw16i16o4i}, |
177 | params_t {{2, 15, 17, 9, 3, 2}, fmt::gOIdhw16i16o2i}); |
178 | } // namespace |
179 | |
180 | INSTANTIATE_TEST_SUITE_P(TestMemoryCreationEF, memory_creation_test_t, |
181 | ::testing::Combine(all_engine_kinds, cases_expect_to_fail)); |
182 | |
183 | INSTANTIATE_TEST_SUITE_P(TestMemoryCreationZeroDim, memory_creation_test_t, |
184 | ::testing::Combine(all_engine_kinds, cases_zero_dim)); |
185 | |
186 | INSTANTIATE_TEST_SUITE_P(TestMemoryCreationOK, memory_creation_test_t, |
187 | ::testing::Combine(all_engine_kinds, cases_generic)); |
188 | |
189 | class c_api_memory_test_t : public ::testing::Test { |
190 | void SetUp() override {} |
191 | }; |
192 | |
193 | TEST_F(c_api_memory_test_t, TestZeroPadBoom) { |
194 | #if defined(DNNL_WITH_SYCL) || DNNL_CPU_RUNTIME == DNNL_RUNTIME_NONE |
195 | SKIP_IF(true, "Test does not support SYCL and GPU only." ); |
196 | #endif |
197 | |
198 | dnnl::impl::memory_desc_t md {}; |
199 | |
200 | md.ndims = 2; |
201 | md.data_type = dnnl_f32; |
202 | md.offset0 = 0; |
203 | md.dims[0] = 1; |
204 | md.dims[1] = 1001; |
205 | md.padded_dims[0] = 1; |
206 | md.padded_dims[1] = 1008; |
207 | md.padded_offsets[0] = 0; |
208 | md.padded_offsets[1] = 0; |
209 | |
210 | md.extra.flags = dnnl::impl::memory_extra_flags::none; |
211 | |
212 | md.format_kind = dnnl_blocked; |
213 | md.format_desc.blocking.inner_nblks = 1; |
214 | md.format_desc.blocking.inner_blks[0] = 16; |
215 | md.format_desc.blocking.inner_idxs[0] = 1; |
216 | md.format_desc.blocking.strides[0] = 1008; |
217 | md.format_desc.blocking.strides[1] = 16; |
218 | |
219 | dnnl_engine_t e; |
220 | ASSERT_TRUE(dnnl_success == dnnl_engine_create(&e, dnnl_cpu, 0)); |
221 | |
222 | dnnl_memory_t m; |
223 | ASSERT_TRUE( |
224 | dnnl_success == dnnl_memory_create(&m, &md, e, DNNL_MEMORY_NONE)); |
225 | |
226 | void *p = malloc(dnnl_memory_desc_get_size(&md)); |
227 | ASSERT_TRUE(p != nullptr); |
228 | ASSERT_TRUE(dnnl_success == dnnl_memory_set_data_handle(m, p)); // Boom |
229 | |
230 | ASSERT_TRUE(dnnl_success == dnnl_memory_destroy(m)); |
231 | free(p); |
232 | |
233 | ASSERT_TRUE(dnnl_success == dnnl_engine_destroy(e)); |
234 | } |
235 | |
236 | #if DNNL_CPU_RUNTIME != DNNL_RUNTIME_DPCPP \ |
237 | && DNNL_CPU_RUNTIME != DNNL_RUNTIME_NONE |
238 | TEST(memory_test_cpp, TestSetDataHandleCPU) { |
239 | engine eng = engine(engine::kind::cpu, 0); |
240 | |
241 | const memory::dim N = 1, C = 5, W = 7, H = 7; |
242 | memory::desc data_md( |
243 | {N, C, W, H}, memory::data_type::f32, memory::format_tag::nChw16c); |
244 | auto mem = test::make_memory(data_md, eng, DNNL_MEMORY_NONE); |
245 | |
246 | float *p = (float *)malloc(mem.get_desc().get_size()); |
247 | ASSERT_TRUE(p != nullptr); |
248 | mem.set_data_handle(p); |
249 | |
250 | ASSERT_TRUE(N == 1); |
251 | ASSERT_TRUE(C < 16); |
252 | ASSERT_TRUE(data_md.get_format_kind() == memory::format_kind::blocked); |
253 | ASSERT_TRUE(data_md.get_inner_nblks() == 1); |
254 | ASSERT_TRUE(data_md.get_inner_blks()[0] == 16); |
255 | |
256 | free(p); |
257 | } |
258 | #endif |
259 | |
260 | } // namespace dnnl |
261 | |