Caffe2 - C++ API
A deep learning, cross platform ML framework
functional.h
1 #pragma once
2 #include <ATen/cpu/vec256/vec256.h>
3 
4 namespace at { namespace vec256 {
5 
6 // TODO: Make this more efficient
7 template <typename scalar_t, typename Op>
8 inline scalar_t vec_reduce_all(
9  const Op& vec_fun,
10  vec256::Vec256<scalar_t> acc_vec,
11  int64_t size) {
12  using Vec = vec256::Vec256<scalar_t>;
13  scalar_t acc_arr[Vec::size()];
14  acc_vec.store(acc_arr);
15  for (int64_t i = 1; i < size; i++) {
16  scalar_t acc_arr_next[Vec::size()];
17  acc_arr_next[0] = acc_arr[i];
18  Vec acc_vec_next = Vec::loadu(acc_arr_next);
19  acc_vec = vec_fun(acc_vec, acc_vec_next);
20  }
21  acc_vec.store(acc_arr);
22  return acc_arr[0];
23 }
24 
25 template <typename scalar_t, typename Op>
26 inline scalar_t reduce_all(const Op& vec_fun, scalar_t* data, int64_t size) {
27  using Vec = vec256::Vec256<scalar_t>;
28  if (size < Vec::size())
29  return vec_reduce_all(vec_fun, Vec::loadu(data, size), size);
30  int64_t d = Vec::size();
31  Vec acc_vec = Vec::loadu(data);
32  for (; d < size - (size % Vec::size()); d += Vec::size()) {
33  Vec data_vec = Vec::loadu(data + d);
34  acc_vec = vec_fun(acc_vec, data_vec);
35  }
36  if (size - d > 0) {
37  Vec data_vec = Vec::loadu(data + d, size - d);
38  acc_vec = Vec::set(acc_vec, vec_fun(acc_vec, data_vec), size - d);
39  }
40  return vec_reduce_all(vec_fun, acc_vec, Vec::size());
41 }
42 
43 template <typename scalar_t, typename MapOp, typename ReduceOp>
44 inline scalar_t map_reduce_all(
45  const MapOp& map_fun,
46  const ReduceOp& red_fun,
47  scalar_t* data,
48  int64_t size) {
49  using Vec = vec256::Vec256<scalar_t>;
50  if (size < Vec::size())
51  return vec_reduce_all(red_fun, map_fun(Vec::loadu(data, size)), size);
52  int64_t d = Vec::size();
53  Vec acc_vec = map_fun(Vec::loadu(data));
54  for (; d < size - (size % Vec::size()); d += Vec::size()) {
55  Vec data_vec = Vec::loadu(data + d);
56  data_vec = map_fun(data_vec);
57  acc_vec = red_fun(acc_vec, data_vec);
58  }
59  if (size - d > 0) {
60  Vec data_vec = Vec::loadu(data + d, size - d);
61  data_vec = map_fun(data_vec);
62  acc_vec = Vec::set(acc_vec, red_fun(acc_vec, data_vec), size - d);
63  }
64  return vec_reduce_all(red_fun, acc_vec, Vec::size());
65 }
66 
67 template <typename scalar_t, typename MapOp, typename ReduceOp>
68 inline scalar_t map2_reduce_all(
69  const MapOp& map_fun,
70  const ReduceOp& red_fun,
71  const scalar_t* data,
72  const scalar_t* data2,
73  int64_t size) {
74  using Vec = vec256::Vec256<scalar_t>;
75  if (size < Vec::size()) {
76  Vec data_vec = Vec::loadu(data, size);
77  Vec data2_vec = Vec::loadu(data2, size);
78  data_vec = map_fun(data_vec, data2_vec);
79  return vec_reduce_all(red_fun, data_vec, size);
80  }
81  int64_t d = Vec::size();
82  Vec acc_vec = map_fun(Vec::loadu(data), Vec::loadu(data2));
83  for (; d < size - (size % Vec::size()); d += Vec::size()) {
84  Vec data_vec = Vec::loadu(data + d);
85  Vec data2_vec = Vec::loadu(data2 + d);
86  data_vec = map_fun(data_vec, data2_vec);
87  acc_vec = red_fun(acc_vec, data_vec);
88  }
89  if (size - d > 0) {
90  Vec data_vec = Vec::loadu(data + d, size - d);
91  Vec data2_vec = Vec::loadu(data2 + d, size - d);
92  data_vec = map_fun(data_vec, data2_vec);
93  acc_vec = Vec::set(acc_vec, red_fun(acc_vec, data_vec), size - d);
94  }
95  return vec_reduce_all(red_fun, acc_vec, Vec::size());
96 }
97 
98 template <typename scalar_t, typename Op>
99 inline void map(
100  const Op& vec_fun,
101  scalar_t* output_data,
102  const scalar_t* input_data,
103  int64_t size) {
104  using Vec = vec256::Vec256<scalar_t>;
105  int64_t d = 0;
106  for (; d < size - (size % Vec::size()); d += Vec::size()) {
107  Vec output_vec = vec_fun(Vec::loadu(input_data + d));
108  output_vec.store(output_data + d);
109  }
110  if (size - d > 0) {
111  Vec output_vec = vec_fun(Vec::loadu(input_data + d, size - d));
112  output_vec.store(output_data + d, size - d);
113  }
114 }
115 
116 template <typename scalar_t, typename Op>
117 inline void map2(
118  const Op& vec_fun,
119  scalar_t* output_data,
120  scalar_t* input_data,
121  scalar_t* input_data2,
122  int64_t size) {
123  using Vec = vec256::Vec256<scalar_t>;
124  int64_t d = 0;
125  for (; d < size - (size % Vec::size()); d += Vec::size()) {
126  Vec data_vec = Vec::loadu(input_data + d);
127  Vec data_vec2 = Vec::loadu(input_data2 + d);
128  Vec output_vec = vec_fun(data_vec, data_vec2);
129  output_vec.store(output_data + d);
130  }
131  if (size - d > 0) {
132  Vec data_vec = Vec::loadu(input_data + d, size - d);
133  Vec data_vec2 = Vec::loadu(input_data2 + d, size - d);
134  Vec output_vec = vec_fun(data_vec, data_vec2);
135  output_vec.store(output_data + d, size - d);
136  }
137 }
138 
139 }} // namespace at::vec256
Flush-To-Zero and Denormals-Are-Zero mode.