1 /*******************************************************************************
2 * Copyright 2019-2021 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:
SetUp()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 
Test()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.data);
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 
TEST_P(memory_creation_test_t,TestsMemoryCreation)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 {
SetUp()190     void SetUp() override {}
191 };
192 
TEST_F(c_api_memory_test_t,TestZeroPadBoom)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_memory_desc_t md;
199     memset(&md, 0xcc, sizeof(md));
200 
201     md.ndims = 2;
202     md.data_type = dnnl_f32;
203     md.offset0 = 0;
204     md.dims[0] = 1;
205     md.dims[1] = 1001;
206     md.padded_dims[0] = 1;
207     md.padded_dims[1] = 1008;
208     md.padded_offsets[0] = 0;
209     md.padded_offsets[1] = 0;
210 
211     md.extra.flags = dnnl_memory_extra_flag_none;
212 
213     md.format_kind = dnnl_blocked;
214     md.format_desc.blocking.inner_nblks = 1;
215     md.format_desc.blocking.inner_blks[0] = 16;
216     md.format_desc.blocking.inner_idxs[0] = 1;
217     md.format_desc.blocking.strides[0] = 1008;
218     md.format_desc.blocking.strides[1] = 16;
219 
220     dnnl_engine_t e;
221     ASSERT_TRUE(dnnl_success == dnnl_engine_create(&e, dnnl_cpu, 0));
222 
223     dnnl_memory_t m;
224     ASSERT_TRUE(
225             dnnl_success == dnnl_memory_create(&m, &md, e, DNNL_MEMORY_NONE));
226 
227     void *p = malloc(dnnl_memory_desc_get_size(&md));
228     ASSERT_TRUE(p != nullptr);
229     ASSERT_TRUE(dnnl_success == dnnl_memory_set_data_handle(m, p)); // Boom
230 
231     ASSERT_TRUE(dnnl_success == dnnl_memory_destroy(m));
232     free(p);
233 
234     ASSERT_TRUE(dnnl_success == dnnl_engine_destroy(e));
235 }
236 
237 #if DNNL_CPU_RUNTIME != DNNL_RUNTIME_DPCPP \
238         && DNNL_CPU_RUNTIME != DNNL_RUNTIME_NONE
TEST(memory_test_cpp,TestSetDataHandleCPU)239 TEST(memory_test_cpp, TestSetDataHandleCPU) {
240     engine eng = engine(engine::kind::cpu, 0);
241     stream str = make_stream(eng);
242 
243     const memory::dim N = 1, C = 5, W = 7, H = 7;
244     memory::desc data_md(
245             {N, C, W, H}, memory::data_type::f32, memory::format_tag::nChw16c);
246     auto mem = test::make_memory(data_md, eng, DNNL_MEMORY_NONE);
247 
248     float *p = (float *)malloc(mem.get_desc().get_size());
249     ASSERT_TRUE(p != nullptr);
250     mem.set_data_handle(p, str);
251 
252     ASSERT_TRUE(N == 1);
253     ASSERT_TRUE(C < 16);
254     ASSERT_TRUE(data_md.data.format_kind == dnnl_blocked);
255     ASSERT_TRUE(data_md.data.format_desc.blocking.inner_nblks == 1);
256     ASSERT_TRUE(data_md.data.format_desc.blocking.inner_blks[0] == 16);
257 
258     free(p);
259 }
260 #endif
261 
262 } // namespace dnnl
263