ONE - On-device Neural Engine
Loading...
Searching...
No Matches
tensor_gen.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <vector>
18#include <iostream>
19#include <fstream>
20#include <stdexcept>
21#include <functional>
22#include <algorithm>
23#include <H5Cpp.h>
24
25using namespace std;
26
27class Tensor;
28
29static void iterate(Tensor &tensor, function<void(vector<int> &)> on_loop);
30
31class Tensor
32{
33public:
34 explicit Tensor(const vector<hsize_t> &shape) : _shape(shape), _data(0), _num_elems(1)
35 {
36 _strides.resize(shape.size());
37
38 for (int i = _shape.size() - 1; i >= 0; --i)
39 {
40 _strides[i] = _num_elems;
41 _num_elems *= _shape[i];
42 }
43
44 _data = new float[_num_elems];
45 }
46
47 ~Tensor() { delete[] _data; }
48 int rank() const { return _shape.size(); }
49 int dim(int d) const { return _shape[d]; }
50 float *data() { return _data; }
51 float numElems() const { return _num_elems; }
52
53 float &at(const vector<int> &coords)
54 {
55 int offset = 0;
56
57 for (auto i = 0; i < coords.size(); ++i)
58 offset += coords[i] * _strides[i];
59
60 return _data[offset];
61 }
62
63 Tensor transpose(const vector<hsize_t> &reshape)
64 {
65 vector<hsize_t> tr_shape(_shape.size());
66
67 for (auto i = 0; i < _shape.size(); ++i)
68 tr_shape[i] = _shape[reshape[i]];
69
70 Tensor result(tr_shape);
71 auto on_loop = [this, &reshape, &result](vector<int> &coords) {
72 vector<int> tr_coords(_shape.size());
73
74 for (int i = 0; i < rank(); ++i)
75 tr_coords[i] = coords[reshape[i]];
76
77 result.at(tr_coords) = at(coords);
78 };
79 iterate(*this, on_loop);
80 return result;
81 }
82
83private:
84 vector<hsize_t> _shape;
85 vector<hsize_t> _strides;
86 float *_data;
87 hsize_t _num_elems;
88};
89
90static void fillTensor(Tensor &tensor)
91{
92 int v = 10;
93
94 for (int i = 0; i < tensor.numElems(); ++i)
95 {
96 tensor.data()[i] = v;
97 v += 10;
98 }
99}
100
101static void iterate(Tensor &tensor, function<void(vector<int> &)> on_loop)
102{
103 int num_dims = tensor.rank();
104 vector<int> coords(num_dims, 0);
105 vector<int> dims(num_dims);
106
107 for (int i = 0; i < num_dims; ++i)
108 dims[i] = tensor.dim(i);
109
110 for (;;)
111 {
112 on_loop(coords);
113
114 int i;
115 for (i = num_dims - 1; i >= 0; --i)
116 {
117 if (coords[i] < dims[i] - 1)
118 {
119 ++coords[i];
120 break;
121 }
122 }
123
124 if (i < 0)
125 break;
126
127 fill(coords.begin() + i + 1, coords.end(), 0);
128 }
129}
130
131static void dumpTensor(Tensor &tensor)
132{
133 auto on_loop = [&tensor](vector<int> &coords) {
134 for (int i = 0; i < tensor.rank(); ++i)
135 {
136 if (i > 0)
137 cout << ", ";
138
139 cout << coords[i];
140 }
141
142 cout << " = " << tensor.at(coords) << endl;
143 };
144
145 iterate(tensor, on_loop);
146}
147
148static void writeTensorToDatFile(const string &file_name, Tensor &tensor)
149{
150 ofstream of(file_name + ".dat", ios_base::binary);
151
152 if (of.fail())
153 cout << "Could not output tensor to the: " << file_name + ".dat";
154
155 of.write(reinterpret_cast<char *>(tensor.data()), tensor.numElems() * sizeof(float));
156}
157
158static void writeTensorToHDF5File(const vector<hsize_t> &dimensions, const string &tensor_name,
159 const string &file_name, Tensor &tensor)
160{
161 H5::H5File h5File(file_name + ".hdf5", H5F_ACC_TRUNC);
162 H5::DataSpace dataspace(dimensions.size(), &dimensions[0]);
163 auto dataset = h5File.createDataSet(tensor_name, H5::PredType::IEEE_F32BE, dataspace);
164 dataset.write(tensor.data(), H5::PredType::NATIVE_FLOAT);
165}
166
167int main(int argc, char *argv[])
168{
169 if (argc < 4)
170 {
171 cout << "Usage: " << argv[0] << " <tensor name> <output file name> dim0, dim1, dim2, ..."
172 << endl;
173 cout << "Where: dim0, dim1, dim2, ... are the generated tensor shape dimensions" << endl;
174 return 1;
175 }
176
177 vector<hsize_t> dimensions;
178
179 for (int i = 3; i < argc; ++i)
180 {
181 try
182 {
183 int d = stoi(argv[i]);
184
185 if (d <= 0)
186 {
187 cout << "The dimensions must be positive values. This is not a correct dimension value: "
188 << d << endl;
189 return 1;
190 }
191
192 dimensions.push_back(d);
193 }
194 catch (const invalid_argument &)
195 {
196 cout << "The parameter does not look as an integer value: " << argv[i] << endl;
197 return 1;
198 }
199 catch (const out_of_range &)
200 {
201 cout << "The value is out of the C++ \"int\" type range: " << argv[i] << endl;
202 return 1;
203 }
204 }
205
206 Tensor caffe_tensor(dimensions);
207 fillTensor(caffe_tensor);
208 writeTensorToHDF5File(dimensions, argv[1], "in_" + string(argv[2]) + "_caffe", caffe_tensor);
209
210 vector<hsize_t> tf_reshape{0, 2, 3, 1};
211 Tensor tf_tensor = caffe_tensor.transpose(tf_reshape);
212 writeTensorToDatFile(string(argv[2]) + "_tf", tf_tensor);
213
214 return 0;
215}
Array< CornerBox > coords
int main(void)
Tensor transpose(const vector< hsize_t > &reshape)
float & at(const vector< int > &coords)
int rank() const
float * data()
float numElems() const
Tensor(const vector< hsize_t > &shape)
int dim(int d) const
__global uchar * offset(const Image *img, int x, int y)
Definition helpers.h:540
NodeFiller< ARG_TYPE_1, ARG_TYPE_2 > fill(ARG_TYPE_1 **arg_1, ARG_TYPE_2 **arg_2)
Definition NodeFiller.h:72