1 /*
2  *Copyright (c) 2018 Intel Corporation.
3  *
4  *Permission is hereby granted, free of charge, to any person obtaining a copy
5  *of this software and associated documentation files (the "Software"), to deal
6  *in the Software without restriction, including without limitation the rights
7  *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  *copies of the Software, and to permit persons to whom the Software is
9  *furnished to do so, subject to the following conditions:
10  *
11  *The above copyright notice and this permission notice shall be included in
12  *all copies or substantial portions of the Software.
13  *
14  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  *THE SOFTWARE.
21  *
22  */
23 
24 
25 #include <numeric>
26 #include <mkldnn_test_common.hpp>
27 #include <gtest/gtest.h>
28 #include <ideep.hpp>
29 
30 #include "test_ideep_common.hpp"
31 
32 using namespace ideep;
33 
34 struct allocator_params {
35   enum {
36     default_alloc = 0,
37     scratch_alloc,
38   };
39   int alloc;
40   test_inner_product_descr_t test_ipd;
41   bool expect_to_fail;
42   mkldnn_status_t expected_status;
43 };
44 
45 template <typename data_t>
46 class allocator_test : public ::testing::TestWithParam<allocator_params> {
47 protected:
SetUp()48   virtual void SetUp() {
49     auto p = ::testing::TestWithParam<allocator_params>::GetParam();
50 
51     auto data_type = data_traits<data_t>::data_type;
52 
53     // Test by inner product forward.
54     auto ipd = p.test_ipd;
55     // Expected format is nchw.
56     // To bring reorder in computation, src is initialized by nChw16c.
57     auto src_desc =
58         tensor::descriptor({ipd.mb, ipd.ic, ipd.kh, ipd.kw}, data_type,
59         static_cast<format>(mkldnn::memory::format::nChw16c));
60     auto wgt_desc =
61         tensor::descriptor({ipd.oc, ipd.ic, ipd.kh, ipd.kw}, data_type,
62         static_cast<format>(mkldnn::memory::format::OIhw16o16i));
63     auto dst_desc =
64         tensor::descriptor({ipd.mb, ipd.oc}, data_type);
65     src_.init(src_desc);
66     wgt_.init(wgt_desc);
67     dst_ref_.init(dst_desc);
68 
69     // tensor cases
70     std::shared_ptr<tensor> src1(new tensor()), src2(new tensor()),
71                             src3(new tensor()), src4(new tensor()),
72                             wgt1(new tensor()), wgt2(new tensor());
73     src1->init<SCRATCH_ALLOCATOR(convolution_forward)>(src_desc);
74     auto raw_src1 = (unsigned long long)src1->get_data_handle();
75     src1.reset();
76     src2->init<SCRATCH_ALLOCATOR(convolution_forward)>(src_desc);
77     auto raw_src2 = (unsigned long long)src2->get_data_handle();
78     ASSERT_EQ(raw_src1, raw_src2);
79 
80     src3->init<SCRATCH_ALLOCATOR(convolution_backward_data)>(src_desc);
81     auto raw_src3 = (unsigned long long)src3->get_data_handle();
82     src3.reset();
83     src4->init<SCRATCH_ALLOCATOR(convolution_backward_data)>(src_desc);
84     auto raw_src4 = (unsigned long long)src4->get_data_handle();
85     ASSERT_EQ(raw_src3, raw_src4);
86 
87     ASSERT_TRUE(raw_src2 != raw_src4);
88 
89     wgt1->init<SCRATCH_ALLOCATOR(convolution_forward)>(wgt_desc);
90     auto raw_wgt1 = (unsigned long long)wgt1->get_data_handle();
91     wgt1.reset();
92     wgt2->init<SCRATCH_ALLOCATOR(convolution_forward)>(wgt_desc);
93     auto raw_wgt2 = (unsigned long long)wgt2->get_data_handle();
94     ASSERT_EQ(raw_wgt1, raw_wgt2);
95     ASSERT_TRUE(raw_wgt2 != raw_src2);
96 
97     src2.reset();
98     src4.reset();
99     wgt2.reset();
100 
101     forward();
102   }
103 
forward()104   void forward() {
105     auto p = ::testing::TestWithParam<allocator_params>::GetParam();
106 
107     fill_tensor(src_);
108     fill_tensor(wgt_);
109 
110     tensor dst;
111     auto test = [&] () {
112       if (p.alloc == allocator_params::default_alloc) {
113         inner_product_forward::compute(src_, wgt_, dst);
114       } else if (p.alloc == allocator_params::scratch_alloc) {
115         inner_product_forward::compute<ideep::utils::scratch_allocator>(
116             src_, wgt_, dst);
117       } else {
118         throw std::invalid_argument("bad arg");
119       }
120     };
121 
122     if (catch_ideep_expected_failures(test, p.expect_to_fail, p.expected_status))
123       return;
124 
125     compute_ref_inner_product_fwd<data_t>(
126         p.test_ipd, src_, wgt_, tensor(), dst_ref_);
127 
128     compare_tensor<float>(dst_ref_, dst);
129   }
130 
131   tensor src_, wgt_, dst_ref_;
132 };
133 
134 using allocator_test_float = allocator_test<float>;
135 using allocator_test_params_float = allocator_params;
136 
TEST_P(allocator_test_float,TestsAllocator)137 TEST_P(allocator_test_float, TestsAllocator) {}
138 
139 INSTANTIATE_TEST_CASE_P(
140     TestAllocators, allocator_test_float, ::testing::Values(
141   // default alloc
142   allocator_test_params_float{ allocator_test_params_float::default_alloc,
143   { 256, 256, 96, 3, 3 } },
144   // push mem
145   allocator_test_params_float{ allocator_test_params_float::scratch_alloc,
146   { 256, 256, 96, 3, 3 } },
147   // pop mem
148   allocator_test_params_float{ allocator_test_params_float::scratch_alloc,
149   { 256, 256, 96, 3, 3 } },
150   // pop mem in same size
151   allocator_test_params_float{ allocator_test_params_float::scratch_alloc,
152   { 256, 256, 96, 9, 1 } }
153 ));
154