broadcast_test.cc 11.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// Copyright (c) 2021 CINN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include "paddle/cinn/frontend/decomposer/test_helper.h"

namespace cinn::frontend {

TEST(Decomposer, elementwise_add_bcast0) {
  NetBuilder builder("elementwise_add");
23 24
  auto x = builder.CreateInput(Float(32), {4, 1, 20, 10});
  auto y = builder.CreateInput(Float(32), {10, 20});
25 26
  auto out = builder.Add(x, y, 1);

27 28
  std::vector<std::string> input_names = {x.id().data(), y.id().data()};
  std::vector<std::string> output_names = {out->id};
29
  std::vector<std::vector<int>> output_shapes = {{4, 10, 20, 10}};
30
  RunAndCheckShape<float>(&builder, input_names, output_names, output_shapes);
31 32 33 34
}

TEST(Decomposer, elementwise_add_bcase1) {
  NetBuilder builder("elementwise_add");
35 36
  auto x = builder.CreateInput(Float(32), {10, 20});
  auto y = builder.CreateInput(Float(32), {4, 1, 20, 10});
37 38
  auto out = builder.Add(x, y, 1);

39 40
  std::vector<std::string> input_names = {x.id().data(), y.id().data()};
  std::vector<std::string> output_names = {out->id};
41
  std::vector<std::vector<int>> output_shapes = {{4, 10, 20, 10}};
42
  RunAndCheckShape<float>(&builder, input_names, output_names, output_shapes);
43 44 45 46
}

TEST(Decomposer, elementwise_add_grad_bcast0) {
  NetBuilder builder("elementwise_add_grad");
47 48 49
  auto dout = builder.CreateInput(Float(32), {4, 10, 20, 10});
  auto x = builder.CreateInput(Float(32), {4, 1, 20, 10});
  auto y = builder.CreateInput(Float(32), {10, 20});
50 51
  auto out_grads = builder.ElementwiseAddGrad(dout, x, y, 1);

52 53
  std::vector<std::string> input_names = {dout.id().data()};
  std::vector<std::string> output_names = {out_grads[0]->id, out_grads[1]->id};
54
  std::vector<std::vector<int>> output_shapes = {{4, 1, 20, 10}, {10, 20}};
55
  RunAndCheckShape<float>(&builder, input_names, output_names, output_shapes);
56 57 58 59
}

TEST(Decomposer, elementwise_add_bcast1) {
  NetBuilder builder("elementwise_add");
60 61
  auto x = builder.CreateInput(Float(32), {32, 64, 32, 32});
  auto y = builder.CreateInput(Float(32), {64});
62 63
  auto out = builder.Add(x, y, 1);

64 65 66 67
  auto add_cpu = [](const std::vector<size_t>& lengths,
                    const std::vector<void*>& ptrs) {
    float* x = static_cast<float*>(ptrs[0]);
    float* y = static_cast<float*>(ptrs[1]);
68 69 70 71
    float* out = static_cast<float*>(ptrs[2]);
    for (size_t i = 0; i < 32; ++i) {
      for (size_t j = 0; j < 64; ++j) {
        for (size_t k = 0; k < 32 * 32; ++k) {
72 73
          out[(i * 64 + j) * 32 * 32 + k] =
              x[(i * 64 + j) * 32 * 32 + k] + y[j];
74 75 76 77 78
        }
      }
    }
  };

79 80
  std::vector<std::string> input_names = {x.id().data(), y.id().data()};
  std::vector<std::string> output_names = {out->id};
81
  std::vector<std::vector<int>> output_shapes = {{32, 64, 32, 32}};
82
  RunAndCheck<float>(
83
      &builder, input_names, output_names, output_shapes, add_cpu);
84 85 86 87
}

TEST(Decomposer, elementwise_add_bcast1_2) {
  NetBuilder builder("elementwise_add");
88 89
  auto x = builder.CreateInput(Float(32), {64});
  auto y = builder.CreateInput(Float(32), {32, 64, 32, 32});
90 91
  auto out = builder.Add(x, y, 1);

92 93 94 95
  auto add_cpu = [](const std::vector<size_t>& lengths,
                    const std::vector<void*>& ptrs) {
    float* x = static_cast<float*>(ptrs[0]);
    float* y = static_cast<float*>(ptrs[1]);
96 97 98 99
    float* out = static_cast<float*>(ptrs[2]);
    for (size_t i = 0; i < 32; ++i) {
      for (size_t j = 0; j < 64; ++j) {
        for (size_t k = 0; k < 32 * 32; ++k) {
100 101
          out[(i * 64 + j) * 32 * 32 + k] =
              y[(i * 64 + j) * 32 * 32 + k] + x[j];
102 103 104 105 106
        }
      }
    }
  };

107 108
  std::vector<std::string> input_names = {x.id().data(), y.id().data()};
  std::vector<std::string> output_names = {out->id};
109
  std::vector<std::vector<int>> output_shapes = {{32, 64, 32, 32}};
110
  RunAndCheck<float>(
111
      &builder, input_names, output_names, output_shapes, add_cpu);
112 113 114 115
}

TEST(Decomposer, elementwise_add_grad_bcast1) {
  NetBuilder builder("elementwise_add_grad");
116 117 118
  auto dout = builder.CreateInput(Float(32), {32, 64, 32, 32});
  auto x = builder.CreateInput(Float(32), {32, 64, 32, 32});
  auto y = builder.CreateInput(Float(32), {64});
119 120
  auto out_grads = builder.ElementwiseAddGrad(dout, x, y, 1);

121 122
  auto add_grad_cpu = [](const std::vector<size_t>& lengths,
                         const std::vector<void*>& ptrs) {
123
    float* dout = static_cast<float*>(ptrs[0]);
124 125
    float* dx = static_cast<float*>(ptrs[1]);
    float* dy = static_cast<float*>(ptrs[2]);
126 127 128 129 130 131 132
    for (size_t j = 0; j < 64; ++j) {
      dy[j] = 0;
    }
    for (size_t i = 0; i < 32; ++i) {
      for (size_t j = 0; j < 64; ++j) {
        for (size_t k = 0; k < 32 * 32; ++k) {
          dx[(i * 64 + j) * 32 * 32 + k] = dout[(i * 64 + j) * 32 * 32 + k];
133
          dy[j] = dy[j] + dout[(i * 64 + j) * 32 * 32 + k];
134 135 136 137 138
        }
      }
    }
  };

139 140
  std::vector<std::string> input_names = {dout.id().data()};
  std::vector<std::string> output_names = {out_grads[0]->id, out_grads[1]->id};
141
  std::vector<std::vector<int>> output_shapes = {{32, 64, 32, 32}, {64}};
142
  RunAndCheck<float>(
143
      &builder, input_names, output_names, output_shapes, add_grad_cpu);
144 145 146 147
}

TEST(Decomposer, elementwise_add_bcast2) {
  NetBuilder builder("elementwise_add");
148 149
  auto x = builder.CreateInput(Float(32), {32, 16});
  auto y = builder.CreateInput(Float(32), {1});
150 151
  auto out = builder.Add(x, y);

152 153 154 155 156 157
  auto add_cpu = [](const std::vector<size_t>& lengths,
                    const std::vector<void*>& ptrs) {
    size_t n = lengths[0];
    float* x = static_cast<float*>(ptrs[0]);
    float* y = static_cast<float*>(ptrs[1]);
    float* out = static_cast<float*>(ptrs[2]);
158 159 160 161 162 163
    float y_data = y[0];
    for (size_t i = 0; i < n; ++i) {
      out[i] = x[i] + y_data;
    }
  };

164 165
  std::vector<std::string> input_names = {x.id().data(), y.id().data()};
  std::vector<std::string> output_names = {out->id};
166
  std::vector<std::vector<int>> output_shapes = {{32, 16}};
167
  RunAndCheck<float>(
168
      &builder, input_names, output_names, output_shapes, add_cpu);
169 170 171 172
}

TEST(Decomposer, elementwise_add_bcast2_2) {
  NetBuilder builder("elementwise_add");
173 174
  auto x = builder.CreateInput(Float(32), {1});
  auto y = builder.CreateInput(Float(32), {32, 16});
175 176
  auto out = builder.Add(x, y);

177 178 179 180 181 182
  auto add_cpu = [](const std::vector<size_t>& lengths,
                    const std::vector<void*>& ptrs) {
    size_t n = 32 * 16;
    float* x = static_cast<float*>(ptrs[0]);
    float* y = static_cast<float*>(ptrs[1]);
    float* out = static_cast<float*>(ptrs[2]);
183 184 185 186 187 188
    float x_data = x[0];
    for (size_t i = 0; i < n; ++i) {
      out[i] = y[i] + x_data;
    }
  };

189 190
  std::vector<std::string> input_names = {x.id().data(), y.id().data()};
  std::vector<std::string> output_names = {out->id};
191
  std::vector<std::vector<int>> output_shapes = {{32, 16}};
192
  RunAndCheck<float>(
193
      &builder, input_names, output_names, output_shapes, add_cpu);
194 195 196 197
}

TEST(Decomposer, elementwise_add_bcast2_3) {
  constexpr int kLength = 64;
198
  using int_ty = int64_t;
199
  NetBuilder builder("elementwise_add");
200 201
  auto x = builder.CreateInput(Int(kLength), {32, 16});
  auto y = builder.CreateInput(Int(kLength), {1});
202 203
  auto out = builder.Add(x, y);

204 205 206 207 208 209
  auto add_cpu = [](const std::vector<size_t>& lengths,
                    const std::vector<void*>& ptrs) {
    size_t n = lengths[0];
    int_ty* x = static_cast<int_ty*>(ptrs[0]);
    int_ty* y = static_cast<int_ty*>(ptrs[1]);
    int_ty* out = static_cast<int_ty*>(ptrs[2]);
210 211 212 213 214 215
    int_ty y_data = y[0];
    for (size_t i = 0; i < n; ++i) {
      out[i] = x[i] + y_data;
    }
  };

216 217
  std::vector<std::string> input_names = {x.id().data(), y.id().data()};
  std::vector<std::string> output_names = {out->id};
218
  std::vector<std::vector<int>> output_shapes = {{32, 16}};
219
  RunAndCheck<int_ty>(
220
      &builder, input_names, output_names, output_shapes, add_cpu);
221 222 223 224
}

TEST(Decomposer, elementwise_add_grad_bcast2) {
  NetBuilder builder("elementwise_add_grad");
225 226 227
  auto dout = builder.CreateInput(Float(32), {32, 16});
  auto x = builder.CreateInput(Float(32), {32, 16});
  auto y = builder.CreateInput(Float(32), {1});
228 229
  auto out_grads = builder.ElementwiseAddGrad(dout, x, y);

230 231 232
  auto add_grad_cpu = [](const std::vector<size_t>& lengths,
                         const std::vector<void*>& ptrs) {
    size_t n = lengths[0];
233
    float* dout = static_cast<float*>(ptrs[0]);
234 235
    float* dx = static_cast<float*>(ptrs[1]);
    float* dy = static_cast<float*>(ptrs[2]);
236 237
    for (size_t i = 0; i < n; ++i) {
      float tmp = dout[i];
238
      dx[i] = tmp;
239 240 241 242
      dy[0] += tmp;
    }
  };

243 244
  std::vector<std::string> input_names = {dout.id().data()};
  std::vector<std::string> output_names = {out_grads[0]->id, out_grads[1]->id};
245
  std::vector<std::vector<int>> output_shapes = {{32, 16}, {1}};
246
  RunAndCheck<float>(
247
      &builder, input_names, output_names, output_shapes, add_grad_cpu);
248 249 250 251
}

TEST(Decomposer, elementwise_add_same_dims) {
  NetBuilder builder("elementwise_add");
252 253
  auto x = builder.CreateInput(Float(32), {32, 16});
  auto y = builder.CreateInput(Float(32), {32, 16});
254 255
  auto out = builder.Add(x, y);

256 257 258 259 260
  auto add_cpu = [](const std::vector<size_t>& lengths,
                    const std::vector<void*>& ptrs) {
    size_t n = lengths[0];
    float* x = static_cast<float*>(ptrs[0]);
    float* y = static_cast<float*>(ptrs[1]);
261 262 263 264 265 266
    float* out = static_cast<float*>(ptrs[2]);
    for (size_t i = 0; i < n; ++i) {
      out[i] = x[i] + y[i];
    }
  };

267 268
  std::vector<std::string> input_names = {x.id().data(), y.id().data()};
  std::vector<std::string> output_names = {out->id};
269
  std::vector<std::vector<int>> output_shapes = {{32, 16}};
270
  RunAndCheck<float>(
271
      &builder, input_names, output_names, output_shapes, add_cpu);
272 273 274 275
}

TEST(Decomposer, elementwise_add_grad_same_dims) {
  NetBuilder builder("elementwise_add_grad");
276 277 278
  auto dout = builder.CreateInput(Float(32), {32, 16});
  auto x = builder.CreateInput(Float(32), {32, 16});
  auto y = builder.CreateInput(Float(32), {32, 16});
279 280
  auto out_grads = builder.ElementwiseAddGrad(dout, x, y);

281 282 283
  auto add_grad_cpu = [](const std::vector<size_t>& lengths,
                         const std::vector<void*>& ptrs) {
    size_t n = lengths[0];
284
    float* dout = static_cast<float*>(ptrs[0]);
285 286
    float* dx = static_cast<float*>(ptrs[1]);
    float* dy = static_cast<float*>(ptrs[2]);
287 288
    for (size_t i = 0; i < n; ++i) {
      float tmp = dout[i];
289 290
      dx[i] = tmp;
      dy[i] = tmp;
291 292 293
    }
  };

294 295
  std::vector<std::string> input_names = {dout.id().data()};
  std::vector<std::string> output_names = {out_grads[0]->id, out_grads[1]->id};
296
  std::vector<std::vector<int>> output_shapes = {{32, 16}, {32, 16}};
297
  RunAndCheck<float>(
298
      &builder, input_names, output_names, output_shapes, add_grad_cpu);
299 300 301
}

}  // namespace cinn::frontend