1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ohos_common.h"
17 #include <numeric>
18 #include <inttypes.h>
19
20 /*
21 * getDimInfo: get dim info from data file(int64_t)
22 * param:
23 * fp: the testing datafile object
24 *
25 * return :
26 * dim_info: array to store the info of the dim in datafile, like
27 * [4,3,3,6,3,162(3*3*6*3)],4 is dim size,3,3,6,3 is the dim shape data_size:
28 * the size of the testing data including the data file
29 * */
getDimInfo(FILE * fp,std::vector<int64_t> * dim_info)30 void getDimInfo(FILE *fp, std::vector<int64_t>* dim_info) {
31 const int MAX_HEAD_SIZE = 50;
32 uint32_t *dim_buffer = reinterpret_cast<uint32_t *>(malloc(MAX_HEAD_SIZE * sizeof(uint32_t)));
33 size_t ret = fread(dim_buffer, sizeof(uint32_t), MAX_HEAD_SIZE, fp);
34 if (ret == 0) {
35 free(dim_buffer);
36 return;
37 }
38 dim_info->push_back(*dim_buffer); // get dim size
39
40 // get data shape to compute the datasize
41 uint64_t data_size = 1;
42 uint32_t i = 1;
43 for (; i <= dim_info->at(0); i++) {
44 dim_info->push_back(*(dim_buffer + i));
45 data_size *= *(dim_buffer + i);
46 }
47 dim_info->push_back(data_size);
48
49 free(dim_buffer);
50 }
51
52 /*
53 * readTestDataFile: read test date from hisi .t datafile(int64_t)
54 * param:
55 * infile: the path of hisi .t datafile
56 * return:
57 * dim_info: array to store the info of the dim in datafile, like [4,3,3,6,3],4
58 * is dim size,3,3,6,3 is the dim shape
59 * */
readTestDataFile(std::string infile,std::vector<int64_t> * dim_info1)60 void *readTestDataFile(std::string infile, std::vector<int64_t>* dim_info1) {
61 printf("\n [common.cpp] Loading data from: %s\n", infile.c_str());
62
63 FILE *fp;
64 fp = fopen(infile.c_str(), "r");
65 if (fp == nullptr) {
66 printf("ERROR: cant't open file %s\n", infile.c_str());
67 return nullptr;
68 } else {
69 std::vector<int64_t> dim_info;
70 std::vector<int64_t>* ptr_dim_info = &dim_info;
71 getDimInfo(fp, ptr_dim_info);
72 uint64_t data_size = ptr_dim_info->at(ptr_dim_info->size() - 1);
73 fclose(fp);
74
75 fp = fopen(infile.c_str(), "r");
76 if (fp == nullptr) {
77 printf("ERROR: cant't open file %s\n", infile.c_str());
78 return nullptr;
79 }
80 uint32_t *memory = reinterpret_cast<uint32_t *>(malloc((dim_info[0] + 1) * sizeof(uint32_t)));
81
82 size_t ret = fread(memory, sizeof(uint32_t), (dim_info[0] + 1), fp);
83 if (ret == 0) {
84 free(memory);
85 fclose(fp);
86 return nullptr;
87 }
88 uint32_t *data = reinterpret_cast<uint32_t *>(malloc((data_size) * sizeof(uint32_t)));
89 size_t ret2 = fread(data, sizeof(uint32_t), data_size, fp);
90 if (ret2 == 0) {
91 free(data);
92 fclose(fp);
93 return nullptr;
94 }
95 free(memory);
96 fclose(fp);
97
98 for (int i = 0; i < dim_info[0]; i++) {
99 dim_info1->push_back(dim_info[i + 1]);
100 }
101
102 printf("\n [common.cpp] Read test data file Over, get dimInfo as: (");
103 int count = dim_info1->size();
104 for (int i = 0; i < count; i++) {
105 printf("%" PRId64, dim_info1->at(i));
106 }
107 printf(")\n");
108 return data;
109 }
110 }
111
112 /*
113 * allclose
114 * param:
115 * a:compared file a
116 * b:compared file b
117 * count: the count size which will compare
118 * rtol:
119 * atol:
120 * return:
121 * true or false
122 * */
allclose(float * a,float * b,uint64_t count,float rtol=1e-05,float atol=1e-08,bool isquant=false)123 bool allclose(float *a, float *b, uint64_t count, float rtol = 1e-05,
124 float atol = 1e-08, bool isquant = false) {
125 uint32_t i = 0;
126
127 // add fail loop print
128 uint32_t fail_count = 0;
129 float tol = 0;
130 float tol1 = 0;
131 float tol2 = 0;
132 bool nan_occur_in_accuray = false;
133
134 float sum = 0.0f;
135 static float sum_all;
136 static float maximum = 0;
137 static float minimum = 0;
138 static uint64_t c = 0;
139
140 if (a == nullptr || b == nullptr) {
141 return false;
142 }
143
144 for (; i < count; ++i) {
145 sum = sum + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
146 sum_all = sum_all + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
147 maximum = max(maximum, fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i])));
148 minimum = min(minimum, fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i])));
149 if (isnan(a[i]) || isinf(a[i])) {
150 fail_count = fail_count + 1;
151 nan_occur_in_accuray = true;
152 if (fail_count < 100) {
153 printf(" i = %2u: %+f | %+f\n", i, a[i], b[i]);
154 }
155 } else if (fabs(a[i] - b[i]) > (atol + rtol * fabs(b[i]))) {
156 tol = tol + fabs(a[i] - b[i]) / (fabs(b[i]) + 1);
157 tol1 = tol1 + fabs(a[i] - b[i]);
158 tol2 = tol2 + fabs(a[i] - b[i]) / fabs(b[i]);
159 fail_count = fail_count + 1;
160 if (fail_count < 100) {
161 printf(" i = %2u: %+f | %+f\n", i, a[i], b[i]);
162 }
163 }
164
165 if (i == count - 1) {
166 printf(" ……\n");
167 printf("\n *** Total fail_count: %u\n", fail_count);
168 printf("\n fabs(a[i] - b[i])/(fabs(b[i])+1) : %f\n",
169 tol / fail_count);
170 printf("\n fabs(a[i] - b[i]) : %f\n", tol1 / fail_count);
171 printf("\n fabs(a[i] - b[i])/fabs(b[i]) : %f\n", tol2 / fail_count);
172
173 c = c + count;
174 printf("\n avg : %f\n", sum / count);
175 printf("\n min : %f\n", minimum);
176 printf("\n max : %f\n", maximum);
177 printf("\n avg_all : %f\n", sum_all / c);
178 printf("\n");
179 fstream file;
180 file.open("cout.csv", ios::app);
181
182 file << ","
183 << "1,"
184 << "0," << maximum;
185 if (fail_count == 0) {
186 file << "," << sum_all / c;
187 } else {
188 file << "," << tol / fail_count;
189 }
190 file.close();
191 }
192 }
193 if (nan_occur_in_accuray) {
194 printf("\n[common.cpp] eval output include some NAN/INF\n");
195 return false;
196 }
197
198 if (fail_count > 0) {
199 printf("\n *** These data compare failed: atol = %f, rtol = %f\n", atol,
200 rtol);
201 printf("\n");
202 if (isquant) {
203 if (tol / fail_count < 0.04) {
204 return true;
205 }
206 }
207 return false;
208 }
209 return true;
210 }
211
allclose_int8(uint8_t * a,uint8_t * b,uint64_t count,float rtol=1e-05,float atol=1e-08,bool isquant=false)212 bool allclose_int8(uint8_t *a, uint8_t *b, uint64_t count, float rtol = 1e-05,
213 float atol = 1e-08, bool isquant = false) {
214 uint32_t i = 0;
215 // add fail loop print
216 uint32_t fail_count = 0;
217 float tol = 0;
218 float tol1 = 0;
219 float tol2 = 0;
220 bool nan_occur_in_accuray = false;
221
222 float sum = 0.0f;
223 static float sum_all;
224 static float maximum = 0;
225 static float minimum = 0;
226 static uint64_t c = 0;
227 // add fail loop print
228
229 if (a == nullptr || b == nullptr) {
230 return false;
231 }
232
233 for (; i < count; ++i) {
234 sum = sum + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
235 sum_all = sum_all + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
236 maximum = max(static_cast<double>(maximum),
237 static_cast<double>(fabs(a[i] - b[i])) / (atol + rtol * fabs(b[i])));
238 minimum = min(static_cast<double>(minimum),
239 static_cast<double>(fabs(a[i] - b[i])) / (atol + rtol * fabs(b[i])));
240 if (isnan(a[i]) || isinf(a[i])) {
241 fail_count = fail_count + 1;
242 nan_occur_in_accuray = true;
243 if (fail_count < 100) {
244 printf(" i = %2u: %+f | %+f\n", i, static_cast<float>(a[i]), static_cast<float>(b[i]));
245 }
246 } else if (fabs(a[i] - b[i]) > 0) {
247 tol = tol + fabs(a[i] - b[i]) / (fabs(b[i]) + 1);
248 tol1 = tol1 + fabs(a[i] - b[i]);
249 tol2 = tol2 + fabs(a[i] - b[i]) / fabs(b[i]);
250 fail_count = fail_count + 1;
251 printf("%2d", static_cast<int>(fabs(a[i] - b[i])));
252 printf(" i = %2u: %2d | %2d\n", i, a[i], b[i]);
253 }
254 if (i == count - 1) {
255 printf(" ……\n");
256 printf("\n *** Total fail_count: %u\n", fail_count);
257 printf("\n fabs(a[i] - b[i])/(fabs(b[i])+1) : %f\n",
258 tol / fail_count);
259 printf("\n fabs(a[i] - b[i]) : %f\n", tol1 / fail_count);
260 printf("\n fabs(a[i] - b[i])/fabs(b[i]) : %f\n", tol2 / fail_count);
261
262 c = c + count;
263 printf("\n avg : %f\n", sum / count);
264 printf("\n min : %f\n", minimum);
265
266 printf("\n max : %f\n", maximum);
267 printf("\n avg_all : %f\n", sum_all / c);
268 printf("\n");
269 fstream file;
270 file.open("cout.csv", ios::app);
271
272 file << ","
273 << "1,"
274 << "0," << maximum;
275 if (fail_count == 0) {
276 file << "," << sum_all / c;
277 } else {
278 file << "," << tol / fail_count;
279 }
280 file.close();
281 }
282 }
283 if (nan_occur_in_accuray) {
284 printf("\n[common.cpp] eval output include some NAN/INF\n");
285 return false;
286 }
287 if (fail_count > 0) {
288 printf("\n *** These data compare failed: atol = %f, rtol = %f\n", atol,
289 rtol);
290 printf("\n");
291 if (isquant) {
292 if (tol / fail_count < 0.04) {
293 return true;
294 }
295 }
296 return false;
297 }
298 return true;
299 }
300
301 /*
302 * compFp32WithTData: compare the data with the data in hisi .t file
303 * param:
304 * actualOutputData: the result of ge
305 * expectedDataFile: the path of hisi .t result file
306 * rtol:
307 * atol:
308 * return:
309 * true of false
310 * */
compFp32WithTData(float * actualOutputData,const std::string & expectedDataFile,float rtol=1e-05,float atol=1e-08,bool isquant=false)311 bool compFp32WithTData(float *actualOutputData, const std::string& expectedDataFile,
312 float rtol = 1e-05, float atol = 1e-08,
313 bool isquant = false) {
314 std::vector<int64_t> dim_info;
315 std::vector<int64_t>* ptr_dim_info = &dim_info;
316 float *expectedOutputData =
317 reinterpret_cast<float *>(readTestDataFile(expectedDataFile, ptr_dim_info));
318 uint32_t i = 0;
319 uint64_t data_size = 1;
320 data_size = accumulate(dim_info.begin(), dim_info.end(), 1, std::multiplies<uint64_t>());
321
322 // print caffe/tf output:
323 printf("[common.cpp] expected output data:");
324 for (; i < data_size && i < 10; i++) {
325 printf("%4f ", expectedOutputData[i]);
326 }
327 printf("\n");
328 if (isquant) {
329 return allclose(actualOutputData, expectedOutputData, data_size, rtol, atol,
330 true);
331 }
332 return allclose(actualOutputData, expectedOutputData, data_size, rtol, atol);
333 }
334
compUint8WithTData(uint8_t * actualOutputData,const std::string & expectedDataFile,float rtol=1e-05,float atol=1e-08,bool isquant=false)335 bool compUint8WithTData(uint8_t *actualOutputData, const std::string& expectedDataFile,
336 float rtol = 1e-05, float atol = 1e-08,
337 bool isquant = false) {
338 std::vector<int64_t> dim_info;
339 std::vector<int64_t>* ptr_dim_info = &dim_info;
340 auto dataFile = readTestDataFile(expectedDataFile, ptr_dim_info);
341 if(dataFile == nullptr){
342 return false;
343 }
344 uint8_t *expectedOutputData =
345 reinterpret_cast<uint8_t *>(dataFile);
346 uint32_t i = 0;
347 uint64_t data_size = 1;
348 data_size = accumulate(dim_info.begin(), dim_info.end(), 1, std::multiplies<uint64_t>());
349
350 // print caffe/tf output:
351 printf("\n [common.cpp] expected output data:\n");
352 for (; i < data_size && i < 10; i++) {
353 printf("%4hhu ", static_cast<unsigned char>(expectedOutputData[i]));
354 }
355 printf("\n");
356 if (isquant) {
357 return allclose_int8(actualOutputData, expectedOutputData, data_size, rtol,
358 atol, true);
359 }
360 return allclose_int8(actualOutputData, expectedOutputData, data_size, rtol,
361 atol);
362 }
363
364 /*
365 * ReadFile: read file of model
366 * param:
367 * file: file location
368 * size: file size
369 * return:
370 * buf of file
371 * */
ReadFile(const char * file,size_t * size)372 char *ReadFile(const char *file, size_t* size) {
373 printf("[common.cpp] Loading data from: %s\n", file);
374
375 std::ifstream ifs(file);
376 if (!ifs.good()) {
377 return nullptr;
378 }
379
380 if (!ifs.is_open()) {
381 ifs.close();
382 return nullptr;
383 }
384
385 ifs.seekg(0, std::ios::end);
386 *size = ifs.tellg();
387
388 char *buf = new char[*size];
389 if (buf == nullptr) {
390 ifs.close();
391 return nullptr;
392 }
393
394 ifs.seekg(0, std::ios::beg);
395 ifs.read(buf, *size);
396 ifs.close();
397 printf("[common.cpp]Read Binary Data Over, get tensorSize as: %" PRId64 ".\n", static_cast<int64_t>(*size));
398
399 return buf;
400 }
401
PackNCHWToNHWCFp32(const char * src,char * dst,int batch,int plane,int channel)402 void PackNCHWToNHWCFp32(const char *src, char *dst, int batch, int plane, int channel) {
403 for (int n = 0; n < batch; n++) {
404 for (int c = 0; c < channel; c++) {
405 for (int hw = 0; hw < plane; hw++) {
406 int nhwc_index = n * channel * plane + hw * channel + c;
407 int nchw_index = n * channel * plane + c * plane + hw;
408 dst[nhwc_index * 4] = src[nchw_index * 4];
409 dst[nhwc_index * 4 + 1] = src[nchw_index * 4 + 1];
410 dst[nhwc_index * 4 + 2] = src[nchw_index * 4 + 2];
411 dst[nhwc_index * 4 + 3] = src[nchw_index * 4 + 3];
412 }
413 }
414 }
415 return;
416 }
417