conv_2d_test.cc 10.2 KB
Newer Older
L
Liangliang He 已提交
1 2 3 4 5
//
// Copyright (c) 2017 XiaoMi All rights reserved.
//

#include "mace/ops/conv_2d.h"
6
#include "mace/ops/ops_test_util.h"
L
Liangliang He 已提交
7 8 9 10 11

using namespace mace;

class Conv2dOpTest : public OpsTestBase {};

12
template<DeviceType D>
L
liuqi 已提交
13 14
void TestSimple3x3VALID() {
  OpsTestNet net;
李寅 已提交
15
  OpDefBuilder("Conv2D", "Conv2dTest")
L
Liangliang He 已提交
16 17 18 19
      .Input("Input")
      .Input("Filter")
      .Input("Bias")
      .Output("Output")
L
Liangliang He 已提交
20 21 22
      .AddIntsArg("strides", {1, 1})
      .AddIntArg("padding", Padding::VALID)
      .AddIntsArg("dilations", {1, 1})
23
      .Finalize(net.NewOperatorDef());
L
Liangliang He 已提交
24 25 26 27

  // Add args

  // Add input data
L
liuqi 已提交
28
  net.AddInputFromArray<D, float>(
L
Liangliang He 已提交
29 30
      "Input", {1, 2, 3, 3},
      {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
L
liuqi 已提交
31
  net.AddInputFromArray<D, float>(
L
Liangliang He 已提交
32 33 34
      "Filter", {1, 2, 3, 3},
      {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
       1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f});
L
liuqi 已提交
35
  net.AddInputFromArray<D, float>("Bias", {1}, {0.1f});
L
Liangliang He 已提交
36 37

  // Run
L
liuqi 已提交
38
  net.RunOp(D);
L
Liangliang He 已提交
39 40

  // Check
李寅 已提交
41
  auto expected = CreateTensor<float>({1, 1, 1, 1}, {18.1f});
L
Liangliang He 已提交
42

李寅 已提交
43
  ExpectTensorNear<float>(*expected, *net.GetOutput("Output"), 0.001);
L
liuqi 已提交
44

L
Liangliang He 已提交
45 46
}

47
template<DeviceType D>
L
liuqi 已提交
48 49
void TestSimple3x3SAME() {
  OpsTestNet net;
李寅 已提交
50
  OpDefBuilder("Conv2D", "Conv2dTest")
L
Liangliang He 已提交
51 52 53 54
      .Input("Input")
      .Input("Filter")
      .Input("Bias")
      .Output("Output")
L
Liangliang He 已提交
55 56 57
      .AddIntsArg("strides", {1, 1})
      .AddIntArg("padding", Padding::SAME)
      .AddIntsArg("dilations", {1, 1})
58
      .Finalize(net.NewOperatorDef());
L
Liangliang He 已提交
59 60

  // Add input data
L
liuqi 已提交
61
  net.AddInputFromArray<D, float>(
L
Liangliang He 已提交
62 63
      "Input", {1, 2, 3, 3},
      {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
L
liuqi 已提交
64
  net.AddInputFromArray<D, float>(
L
Liangliang He 已提交
65 66 67
      "Filter", {1, 2, 3, 3},
      {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
       1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f});
L
liuqi 已提交
68
  net.AddInputFromArray<D, float>("Bias", {1}, {0.1f});
L
Liangliang He 已提交
69 70

  // Run
L
liuqi 已提交
71
  net.RunOp(D);
L
Liangliang He 已提交
72 73

  // Check
L
Liangliang He 已提交
74 75 76
  auto expected = CreateTensor<float>(
      {1, 1, 3, 3},
      {8.1f, 12.1f, 8.1f, 12.1f, 18.1f, 12.1f, 8.1f, 12.1f, 8.1f});
L
Liangliang He 已提交
77

李寅 已提交
78
  ExpectTensorNear<float>(*expected, *net.GetOutput("Output"), 0.001);
L
Liangliang He 已提交
79 80
}

L
liuqi 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
TEST_F(Conv2dOpTest, CPUSimple) {
  TestSimple3x3VALID<DeviceType::CPU>();
  TestSimple3x3SAME<DeviceType::CPU>();
}

TEST_F(Conv2dOpTest, NEONSimple) {
  TestSimple3x3VALID<DeviceType::NEON>();
  TestSimple3x3SAME<DeviceType::NEON>();
}

TEST_F(Conv2dOpTest, OPENCLSimple) {
  TestSimple3x3VALID<DeviceType::OPENCL>();
  TestSimple3x3SAME<DeviceType::OPENCL>();
}

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
template<DeviceType D>
void TestSimple3x3WithoutBias() {
  OpsTestNet net;
  OpDefBuilder("Conv2D", "Conv2dTest")
      .Input("Input")
      .Input("Filter")
      .Output("Output")
      .AddIntsArg("strides", {1, 1})
      .AddIntArg("padding", Padding::VALID)
      .AddIntsArg("dilations", {1, 1})
      .Finalize(net.NewOperatorDef());

  // Add args

  // Add input data
  net.AddInputFromArray<D, float>(
      "Input", {1, 2, 3, 3},
      {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
  net.AddInputFromArray<D, float>(
      "Filter", {1, 2, 3, 3},
      {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
       1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f});

  // Run
  net.RunOp(D);

  // Check
  auto expected = CreateTensor<float>({1, 1, 1, 1}, {18.0f});

  ExpectTensorNear<float>(*expected, *net.GetOutput("Output"), 0.001);
}

TEST_F(Conv2dOpTest, CPUWithoutBias) {
  TestSimple3x3WithoutBias<DeviceType::CPU>();
}

TEST_F(Conv2dOpTest, NEONWithouBias) {
  TestSimple3x3WithoutBias<DeviceType::NEON>();
}

TEST_F(Conv2dOpTest, OPENCLWithoutBias) {
  TestSimple3x3WithoutBias<DeviceType::OPENCL>();
}

template<DeviceType D>
L
liuqi 已提交
141
static void TestCombined3x3() {
L
Liangliang He 已提交
142
  // Construct graph
L
liuqi 已提交
143
  OpsTestNet net;
李寅 已提交
144
  OpDefBuilder("Conv2D", "Conv2DTest")
L
Liangliang He 已提交
145 146 147 148
      .Input("Input")
      .Input("Filter")
      .Input("Bias")
      .Output("Output")
L
Liangliang He 已提交
149 150 151
      .AddIntsArg("strides", {2, 2})
      .AddIntArg("padding", Padding::SAME)
      .AddIntsArg("dilations", {1, 1})
152
      .Finalize(net.NewOperatorDef());
L
Liangliang He 已提交
153 154

  // Add input data
L
liuqi 已提交
155
  net.AddInputFromArray<D, float>(
L
Liangliang He 已提交
156 157 158
      "Input", {1, 2, 5, 5}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
L
liuqi 已提交
159
  net.AddInputFromArray<D, float>(
L
Liangliang He 已提交
160 161 162 163
      "Filter", {2, 2, 3, 3},
      {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
       1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
       0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f});
L
liuqi 已提交
164
  net.AddInputFromArray<D, float>("Bias", {2}, {0.1f, 0.2f});
L
Liangliang He 已提交
165 166

  // Run
L
liuqi 已提交
167
  net.RunOp(D);
L
Liangliang He 已提交
168 169

  // Check
L
Liangliang He 已提交
170 171 172
  auto expected = CreateTensor<float>(
      {1, 2, 3, 3}, {8.1f, 12.1f, 8.1f, 12.1f, 18.1f, 12.1f, 8.1f, 12.1f, 8.1f,
                     4.2f, 6.2f, 4.2f, 6.2f, 9.2f, 6.2f, 4.2f, 6.2f, 4.2f});
L
Liangliang He 已提交
173

李寅 已提交
174
  ExpectTensorNear<float>(*expected, *net.GetOutput("Output"), 0.001);
L
liuqi 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187

}

TEST_F(Conv2dOpTest, CPUCombined) {
  TestCombined3x3<DeviceType::CPU>();
}

TEST_F(Conv2dOpTest, NEONCombined) {
  TestCombined3x3<DeviceType::NEON>();
}

TEST_F(Conv2dOpTest, OPENCLCombined) {
  TestCombined3x3<DeviceType::OPENCL>();
L
Liangliang He 已提交
188 189
}

190
template<DeviceType D>
191
void TestConv1x1() {
L
Liangliang He 已提交
192
  // Construct graph
193
  OpsTestNet net;
李寅 已提交
194
  OpDefBuilder("Conv2D", "Conv2DTest")
L
Liangliang He 已提交
195 196 197 198
      .Input("Input")
      .Input("Filter")
      .Input("Bias")
      .Output("Output")
L
Liangliang He 已提交
199 200 201
      .AddIntsArg("strides", {1, 1})
      .AddIntArg("padding", Padding::VALID)
      .AddIntsArg("dilations", {1, 1})
202
      .Finalize(net.NewOperatorDef());
L
Liangliang He 已提交
203 204

  // Add input data
205
  net.AddInputFromArray<D, float>(
L
Liangliang He 已提交
206 207 208 209 210 211 212 213
      "Input", {1, 5, 3, 10},
      {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
214
  net.AddInputFromArray<D, float>(
L
Liangliang He 已提交
215 216
      "Filter", {2, 5, 1, 1},
      {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f});
217
  net.AddInputFromArray<D, float>("Bias", {2}, {0.1f, 0.2f});
L
Liangliang He 已提交
218 219

  // Run
220
  net.RunOp(D);
L
Liangliang He 已提交
221 222

  // Check
L
Liangliang He 已提交
223 224
  auto expected = CreateTensor<float>(
      {1, 2, 3, 10},
225 226 227
      {5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f,
       5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f,
       5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f, 5.1f,
L
Liangliang He 已提交
228 229 230
       10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f,
       10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f,
       10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f, 10.2f});
L
Liangliang He 已提交
231

李寅 已提交
232
  ExpectTensorNear<float>(*expected, *net.GetOutput("Output"), 0.001);
L
Liangliang He 已提交
233 234
}

L
liuqi 已提交
235
TEST_F(Conv2dOpTest, CPUConv1x1) {
236
  TestConv1x1<DeviceType::CPU>();
L
liuqi 已提交
237 238 239
}

TEST_F(Conv2dOpTest, OPENCLConv1x1) {
240 241 242
  TestConv1x1<DeviceType::OPENCL>();
}

243
template<DeviceType D>
L
liuqi 已提交
244
static void TestAlignedConvNxNS12() {
李寅 已提交
245
  testing::internal::LogToStderr();
L
Liangliang He 已提交
246
  auto func = [&](int kernel_h, int kernel_w, int stride_h, int stride_w,
247
                  Padding type) {
248 249 250
    srand(time(NULL));

    // generate random input
L
Liangliang He 已提交
251
    index_t batch = 3;
L
liuqi 已提交
252 253 254 255 256
    index_t input_channels = 64;
    index_t height = 32;
    index_t width = 32;
    index_t output_channels = 128;
    // Construct graph
L
liuqi 已提交
257
    OpsTestNet net;
L
liuqi 已提交
258 259 260 261 262
    OpDefBuilder("Conv2D", "Conv2dTest")
        .Input("Input")
        .Input("Filter")
        .Input("Bias")
        .Output("Output")
L
Liangliang He 已提交
263 264 265
        .AddIntsArg("strides", {stride_h, stride_w})
        .AddIntArg("padding", type)
        .AddIntsArg("dilations", {1, 1})
266
        .Finalize(net.NewOperatorDef());
L
liuqi 已提交
267 268

    // Add input data
L
liuqi 已提交
269 270
    net.AddRandomInput<D, float>("Input", {batch, input_channels, height, width});
    net.AddRandomInput<D, float>(
L
liuqi 已提交
271
        "Filter", {output_channels, input_channels, kernel_h, kernel_w});
L
liuqi 已提交
272 273 274
    net.AddRandomInput<D, float>("Bias", {output_channels});
    // Run on device
    net.RunOp(D);
L
liuqi 已提交
275 276 277 278 279

    // Check
    Tensor expected;
    expected.Copy(*net.GetOutput("Output"));

L
liuqi 已提交
280 281
    // run cpu
    net.RunOp();
L
liuqi 已提交
282 283 284
    ExpectTensorNear<float>(expected, *net.GetOutput("Output"), 0.001);
  };

285 286
  for (int kernel_size : {1, 3, 5}) {
    for (int stride : {1, 2}) {
L
liuqi 已提交
287 288 289 290 291 292
      func(kernel_size, kernel_size, stride, stride, VALID);
      func(kernel_size, kernel_size, stride, stride, SAME);
    }
  }
}

L
liuqi 已提交
293 294 295 296 297 298 299 300
TEST_F(Conv2dOpTest, NEONAlignedConvNxNS12) {
  TestAlignedConvNxNS12<DeviceType::NEON>();
}

TEST_F(Conv2dOpTest, OPENCLAlignedConvNxNS12) {
  TestAlignedConvNxNS12<DeviceType::OPENCL>();
}

301
template<DeviceType D>
L
liuqi 已提交
302
static void TestUnalignedConvNxNS12() {
L
liuqi 已提交
303 304 305 306 307 308 309 310
  testing::internal::LogToStderr();
  auto func = [&](int kernel_h, int kernel_w, int stride_h, int stride_w,
                  Padding type) {
    srand(time(NULL));

    // generate random input
    index_t batch = 3 + rand() % 10;
    index_t input_channels = 3 + rand() % 10;
311 312
    index_t height = 107;
    index_t width = 113;
L
liuqi 已提交
313
    index_t output_channels = 3 + rand() % 10;
314
    // Construct graph
L
liuqi 已提交
315
    OpsTestNet net;
李寅 已提交
316
    OpDefBuilder("Conv2D", "Conv2dTest")
李寅 已提交
317 318 319 320
        .Input("Input")
        .Input("Filter")
        .Input("Bias")
        .Output("Output")
L
Liangliang He 已提交
321 322 323
        .AddIntsArg("strides", {stride_h, stride_w})
        .AddIntArg("padding", type)
        .AddIntsArg("dilations", {1, 1})
324
        .Finalize(net.NewOperatorDef());
325 326

    // Add input data
L
liuqi 已提交
327 328
    net.AddRandomInput<D, float>("Input", {batch, input_channels, height, width});
    net.AddRandomInput<D, float>(
L
Liangliang He 已提交
329
        "Filter", {output_channels, input_channels, kernel_h, kernel_w});
L
liuqi 已提交
330 331 332
    net.AddRandomInput<D, float>("Bias", {output_channels});
    // Run on device
    net.RunOp(D);
333 334

    // Check
L
Liangliang He 已提交
335
    Tensor expected;
李寅 已提交
336
    expected.Copy(*net.GetOutput("Output"));
337

L
liuqi 已提交
338 339
    // run cpu
    net.RunOp();
李寅 已提交
340
    ExpectTensorNear<float>(expected, *net.GetOutput("Output"), 0.001);
341 342
  };

李寅 已提交
343
  for (int kernel_size : {1, 3, 5}) {
L
liuqi 已提交
344
    for (int stride : {1, 2}) {
345 346 347 348
      func(kernel_size, kernel_size, stride, stride, VALID);
      func(kernel_size, kernel_size, stride, stride, SAME);
    }
  }
349
}
L
liuqi 已提交
350 351 352 353 354 355 356 357

TEST_F(Conv2dOpTest, NEONUnalignedConvNxNS12) {
  TestUnalignedConvNxNS12<DeviceType::NEON>();
}

TEST_F(Conv2dOpTest, OPENCLUnalignedConvNxNS12) {
  TestUnalignedConvNxNS12<DeviceType::OPENCL>();
}