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