Caffe2 - C++ API
A deep learning, cross platform ML framework
apply_utils_test.cpp
1 #include <gtest/gtest.h>
2 
3 #include <ATen/ATen.h>
4 #include <ATen/CPUApplyUtils.h>
5 #include <ATen/test/test_assert.h>
6 
7 #include <iostream>
8 using namespace std;
9 using namespace at;
10 
11 void fill_tensor(int64_t scalar, Tensor& t_) {
12  auto t = t_.view(-1);
13  for (int64_t i = 0; i < t.numel(); i++) {
14  t[i] = (i + 1) * scalar;
15  }
16 }
17 
18 // This test exercises all sequential applyX functions. Given a shape and two
19 // transpose dimensions we create 5 tensors (a0, ..., a4) of the given shape and
20 // transpose the dimension a with b for each tensor. Then we call the applyX
21 // function on each floating type. a4 is allocated in doubles only, whereas a0,
22 // ..., a3 are allocated in the given type. For each applyX function we once
23 // write the same type as we read (using a0, ..., aX-1) and we once write to
24 // double (using a4 as a target). We also exercise on a zero_dim and empty
25 // tensor.
26 void test(Type& type, IntArrayRef shape, int64_t a = 0, int64_t b = 1) {
27  auto zero_dim = at::empty({}, type);
28  zero_dim.fill_(2);
29  zero_dim.exp_();
30  AT_DISPATCH_FLOATING_TYPES(zero_dim.scalar_type(), "test0", [&] {
31  ASSERT(zero_dim.data<scalar_t>()[0] == std::exp(2));
32  });
33 
34  auto empty_t = at::empty({0}, type);
35  empty_t.fill_(3);
36  empty_t.exp_();
37 
38  auto a0 = at::empty({0}, type.options());
39  auto a1 = at::empty({0}, type.options());
40  auto a2 = at::empty({0}, type.options());
41  auto a3 = at::empty({0}, type.options());
42  auto a4 = at::empty({0}, at::TensorOptions(kCPU).dtype(kDouble));
43 
44  std::vector<Tensor> tensors({a0, a1, a2, a3, a4});
45  for (size_t i = 0; i < tensors.size(); i++) {
46  tensors[i].resize_(shape);
47  fill_tensor(i + 1, tensors[i]);
48  if (a >= 0 && b >= 0) {
49  tensors[i].transpose_(a, b);
50  }
51  }
52 
53  AT_DISPATCH_FLOATING_TYPES(a0.scalar_type(), "test1", [&] {
54  CPU_tensor_apply2<scalar_t, scalar_t>(
55  a0, a1, [](scalar_t& y, const scalar_t& x) { y = x * x; });
56  CPU_tensor_apply2<double, scalar_t>(
57  a4, a1, [](double& y, scalar_t x) { y = (double)(x * x); });
58  for (int64_t i = 0; i < a0.numel(); i++) {
59  auto target = a1.data<scalar_t>()[i] * a1.data<scalar_t>()[i];
60  ASSERT(a0.data<scalar_t>()[i] == target);
61  ASSERT(a4.data<double>()[i] == target);
62  }
63  });
64 
65  AT_DISPATCH_FLOATING_TYPES(a0.scalar_type(), "test2", [&] {
66  CPU_tensor_apply3<scalar_t, scalar_t, scalar_t>(
67  a0, a1, a2, [](scalar_t& y, const scalar_t& x, const scalar_t& z) {
68  y = x * x + z;
69  });
70  CPU_tensor_apply3<double, scalar_t, scalar_t>(
71  a4, a1, a2, [](double& y, const scalar_t& x, const scalar_t& z) {
72  y = (double)(x * x + z);
73  });
74  for (int64_t i = 0; i < a0.numel(); i++) {
75  auto target = a1.data<scalar_t>()[i] * a1.data<scalar_t>()[i];
76  target = target + a2.data<scalar_t>()[i];
77  ASSERT(a0.data<scalar_t>()[i] == target);
78  ASSERT(a4.data<double>()[i] == target);
79  }
80  });
81 
82  AT_DISPATCH_FLOATING_TYPES(a0.scalar_type(), "test3", [&] {
83  CPU_tensor_apply4<scalar_t, scalar_t, scalar_t, scalar_t>(
84  a0,
85  a1,
86  a2,
87  a3,
88  [](scalar_t& y,
89  const scalar_t& x,
90  const scalar_t& z,
91  const scalar_t& a) { y = x * x + z * a; });
92  CPU_tensor_apply4<double, scalar_t, scalar_t, scalar_t>(
93  a4,
94  a1,
95  a2,
96  a3,
97  [](double& y, const scalar_t& x, const scalar_t& z, const scalar_t& a) {
98  y = (double)(x * x + z * a);
99  });
100  for (int64_t i = 0; i < a0.numel(); i++) {
101  auto target = a1.data<scalar_t>()[i] * a1.data<scalar_t>()[i];
102  target = target + a2.data<scalar_t>()[i] * a3.data<scalar_t>()[i];
103  ASSERT(a0.data<scalar_t>()[i] == target);
104  ASSERT(a4.data<double>()[i] == target);
105  }
106  });
107 }
108 
109 // apply utils test 2-dim small contiguous
110 TEST(ApplyUtilsTest, Contiguous2D) {
111  manual_seed(123);
112  test(CPU(kDouble), {2, 1}, -1, -1);
113 }
114 
115 // apply utils test 2-dim small
116 TEST(ApplyUtilsTest, Small2D) {
117  manual_seed(123);
118  test(CPU(kDouble), {2, 1});
119 }
120 
121 // apply utils test 2-dim
122 TEST(ApplyUtilsTest, _2D) {
123  manual_seed(123);
124  test(CPU(kDouble), {20, 10});
125 }
126 
127 // apply utils test 3-dim
128 TEST(ApplyUtilsTest, _3D) {
129  manual_seed(123);
130  test(CPU(kDouble), {3, 4, 2});
131 }
132 
133 // apply utils test 3-dim medium
134 TEST(ApplyUtilsTest, Medium3D) {
135  manual_seed(123);
136  test(CPU(kDouble), {3, 40, 2});
137 }
138 
139 // apply utils test 10-dim
140 TEST(ApplyUtilsTest, _10D) {
141  manual_seed(123);
142  test(CPU(kDouble), {3, 4, 2, 5, 2, 1, 3, 4, 2, 3});
143 }
Definition: module.cpp:17
C10_NODISCARD TensorOptions dtype(c10::optional< caffe2::TypeMeta > dtype) const noexcept
Return a copy of TensorOptions with dtype set to the given one.
Flush-To-Zero and Denormals-Are-Zero mode.