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 #include <sys/time.h>
20 #include <unistd.h>
21 #include <cfloat>
22 #include <climits>
23 #include <cstdint>
24 #include <cstdlib>
25 #include <cstring>
26 #include <string>
27 #include <iostream>
28 #include <functional>
29 #include <ctime>
30 #include <cstdio>
31 #include <fstream>
32 #include <vector>
33 #include <map>
34 #include <cmath>
35 #include <regex>
36 #include <sstream>
37 #include <malloc.h>
38 #include <numeric>
39 /*
40 * getDimInfo: get dim info from data file(int64_t)
41 * param:
42 * fp: the testing datafile object
43 *
44 * return :
45 * dim_info: array to store the info of the dim in datafile, like
46 * [4,3,3,6,3,162(3*3*6*3)],4 is dim size,3,3,6,3 is the dim shape data_size:
47 * the size of the testing data including the data file
48 * */
getDimInfo(FILE *fp, std::vector<int64_t>* dim_info)49 void getDimInfo(FILE *fp, std::vector<int64_t>* dim_info) {
50 const int MAX_HEAD_SIZE = 50;
51 uint32_t *dim_buffer = reinterpret_cast<uint32_t *>(malloc(MAX_HEAD_SIZE * sizeof(uint32_t)));
52 size_t ret = fread(dim_buffer, sizeof(uint32_t), MAX_HEAD_SIZE, fp);
53 if (ret == 0) {
54 free(dim_buffer);
55 return;
56 }
57 dim_info->push_back(*dim_buffer); // get dim size
58
59 // get data shape to compute the datasize
60 uint64_t data_size = 1;
61 uint32_t i = 1;
62 for (; i <= dim_info->at(0); i++) {
63 dim_info->push_back(*(dim_buffer + i));
64 data_size *= *(dim_buffer + i);
65 }
66 dim_info->push_back(data_size);
67
68 free(dim_buffer);
69 }
70
71 /*
72 * readTestDataFile: read test date from hisi .t datafile(int64_t)
73 * param:
74 * infile: the path of hisi .t datafile
75 * return:
76 * dim_info: array to store the info of the dim in datafile, like [4,3,3,6,3],4
77 * is dim size,3,3,6,3 is the dim shape
78 * */
readTestDataFile(std::string infile, std::vector<int64_t>* dim_info1)79 void *readTestDataFile(std::string infile, std::vector<int64_t>* dim_info1) {
80 printf("\n [common.cpp] Loading data from: %s\n", infile.c_str());
81
82 FILE *fp;
83 fp = fopen(infile.c_str(), "r");
84 if (fp == nullptr) {
85 printf("ERROR: cant't open file %s\n", infile.c_str());
86 return nullptr;
87 } else {
88 std::vector<int64_t> dim_info;
89 std::vector<int64_t>* ptr_dim_info = &dim_info;
90 getDimInfo(fp, ptr_dim_info);
91 uint64_t data_size = ptr_dim_info->at(ptr_dim_info->size() - 1);
92 fclose(fp);
93
94 fp = fopen(infile.c_str(), "r");
95 if (fp == nullptr) {
96 printf("ERROR: cant't open file %s\n", infile.c_str());
97 return nullptr;
98 }
99 uint32_t *memory = reinterpret_cast<uint32_t *>(malloc((dim_info[0] + 1) * sizeof(uint32_t)));
100
101 size_t ret = fread(memory, sizeof(uint32_t), (dim_info[0] + 1), fp);
102 if (ret == 0) {
103 free(memory);
104 fclose(fp);
105 return nullptr;
106 }
107 uint32_t *data = reinterpret_cast<uint32_t *>(malloc((data_size) * sizeof(uint32_t)));
108 size_t ret2 = fread(data, sizeof(uint32_t), data_size, fp);
109 if (ret2 == 0) {
110 free(data);
111 fclose(fp);
112 return nullptr;
113 }
114 free(memory);
115 fclose(fp);
116
117 for (int i = 0; i < dim_info[0]; i++) {
118 dim_info1->push_back(dim_info[i + 1]);
119 }
120
121 printf("\n [common.cpp] Read test data file Over, get dimInfo as: (");
122 int count = dim_info1->size();
123 for (int i = 0; i < count; i++) {
124 printf("%" PRId64, dim_info1->at(i));
125 }
126 printf(")\n");
127 return data;
128 }
129 }
130
131 /*
132 * allclose
133 * param:
134 * a:compared file a
135 * b:compared file b
136 * count: the count size which will compare
137 * rtol:
138 * atol:
139 * return:
140 * true or false
141 * */
allclose(float *a, float *b, uint64_t count, float rtol = 1e-05, float atol = 1e-08, bool isquant = false)142 bool allclose(float *a, float *b, uint64_t count, float rtol = 1e-05,
143 float atol = 1e-08, bool isquant = false) {
144 uint32_t i = 0;
145
146 // add fail loop print
147 uint32_t fail_count = 0;
148 float tol = 0;
149 float tol1 = 0;
150 float tol2 = 0;
151 bool nan_occur_in_accuray = false;
152
153 float sum = 0.0f;
154 static float sum_all;
155 static float maximum = 0;
156 static float minimum = 0;
157 static uint64_t c = 0;
158
159 if (a == nullptr || b == nullptr) {
160 return false;
161 }
162
163 for (; i < count; ++i) {
164 sum = sum + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
165 sum_all = sum_all + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
166 maximum = max(maximum, fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i])));
167 minimum = min(minimum, fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i])));
168 if (isnan(a[i]) || isinf(a[i])) {
169 fail_count = fail_count + 1;
170 nan_occur_in_accuray = true;
171 if (fail_count < 100) {
172 printf(" i = %2u: %+f | %+f\n", i, a[i], b[i]);
173 }
174 } else if (fabs(a[i] - b[i]) > (atol + rtol * fabs(b[i]))) {
175 tol = tol + fabs(a[i] - b[i]) / (fabs(b[i]) + 1);
176 tol1 = tol1 + fabs(a[i] - b[i]);
177 tol2 = tol2 + fabs(a[i] - b[i]) / fabs(b[i]);
178 fail_count = fail_count + 1;
179 if (fail_count < 100) {
180 printf(" i = %2u: %+f | %+f\n", i, a[i], b[i]);
181 }
182 }
183
184 if (i == count - 1) {
185 printf(" ......\n");
186 printf("\n *** Total fail_count: %u\n", fail_count);
187 if (fail_count != 0) {
188 printf("\n fabs(a[i] - b[i])/(fabs(b[i])+1) : %f\n",
189 tol / fail_count);
190 printf("\n fabs(a[i] - b[i]) : %f\n", tol1 / fail_count);
191 printf("\n fabs(a[i] - b[i])/fabs(b[i]) : %f\n", tol2 / fail_count);
192 }
193 c = c + count;
194 printf("\n avg : %f\n", sum / count);
195 printf("\n min : %f\n", minimum);
196 printf("\n max : %f\n", maximum);
197 printf("\n avg_all : %f\n", sum_all / c);
198 printf("\n");
199 fstream file;
200 file.open("cout.csv", ios::app);
201
202 file << ","
203 << "1,"
204 << "0," << maximum;
205 if (fail_count == 0) {
206 file << "," << sum_all / c;
207 } else {
208 file << "," << tol / fail_count;
209 }
210 file.close();
211 }
212 }
213 if (nan_occur_in_accuray) {
214 printf("\n[common.cpp] eval output include some NAN/INF\n");
215 return false;
216 }
217
218 if (fail_count > 0) {
219 printf("\n *** These data compare failed: atol = %f, rtol = %f\n", atol,
220 rtol);
221 printf("\n");
222 if (isquant) {
223 if (tol / fail_count < 0.04) {
224 return true;
225 }
226 }
227 return false;
228 }
229 return true;
230 }
231
allclose_int8(uint8_t *a, uint8_t *b, uint64_t count, float rtol = 1e-05, float atol = 1e-08, bool isquant = false)232 bool allclose_int8(uint8_t *a, uint8_t *b, uint64_t count, float rtol = 1e-05,
233 float atol = 1e-08, bool isquant = false) {
234 uint32_t i = 0;
235 // add fail loop print
236 uint32_t fail_count = 0;
237 float tol = 0;
238 float tol1 = 0;
239 float tol2 = 0;
240 bool nan_occur_in_accuray = false;
241
242 float sum = 0.0f;
243 static float sum_all;
244 static float maximum = 0;
245 static float minimum = 0;
246 static uint64_t c = 0;
247 // add fail loop print
248
249 if (a == nullptr || b == nullptr) {
250 return false;
251 }
252
253 for (; i < count; ++i) {
254 sum = sum + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
255 sum_all = sum_all + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
256 maximum = max(static_cast<double>(maximum),
257 static_cast<double>(fabs(a[i] - b[i])) / (atol + rtol * fabs(b[i])));
258 minimum = min(static_cast<double>(minimum),
259 static_cast<double>(fabs(a[i] - b[i])) / (atol + rtol * fabs(b[i])));
260 if (isnan(a[i]) || isinf(a[i])) {
261 fail_count = fail_count + 1;
262 nan_occur_in_accuray = true;
263 if (fail_count < 100) {
264 printf(" i = %2u: %+f | %+f\n", i, static_cast<float>(a[i]), static_cast<float>(b[i]));
265 }
266 } else if (fabs(a[i] - b[i]) > 0) {
267 tol = tol + fabs(a[i] - b[i]) / (fabs(b[i]) + 1);
268 tol1 = tol1 + fabs(a[i] - b[i]);
269 tol2 = tol2 + fabs(a[i] - b[i]) / fabs(b[i]);
270 fail_count = fail_count + 1;
271 printf("%2d", static_cast<int>(fabs(a[i] - b[i])));
272 printf(" i = %2u: %2d | %2d\n", i, a[i], b[i]);
273 }
274 if (i == count - 1) {
275 printf(" ……\n");
276 printf("\n *** Total fail_count: %u\n", fail_count);
277 if (fail_count != 0) {
278 printf("\n fabs(a[i] - b[i])/(fabs(b[i])+1) : %f\n",
279 tol / fail_count);
280 printf("\n fabs(a[i] - b[i]) : %f\n", tol1 / fail_count);
281 printf("\n fabs(a[i] - b[i])/fabs(b[i]) : %f\n", tol2 / fail_count);
282 }
283
284 c = c + count;
285 printf("\n avg : %f\n", sum / count);
286 printf("\n min : %f\n", minimum);
287
288 printf("\n max : %f\n", maximum);
289 printf("\n avg_all : %f\n", sum_all / c);
290 printf("\n");
291 fstream file;
292 file.open("cout.csv", ios::app);
293
294 file << ","
295 << "1,"
296 << "0," << maximum;
297 if (fail_count == 0) {
298 file << "," << sum_all / c;
299 } else {
300 file << "," << tol / fail_count;
301 }
302 file.close();
303 }
304 }
305 if (nan_occur_in_accuray) {
306 printf("\n[common.cpp] eval output include some NAN/INF\n");
307 return false;
308 }
309 if (fail_count > 0) {
310 printf("\n *** These data compare failed: atol = %f, rtol = %f\n", atol,
311 rtol);
312 printf("\n");
313 if (isquant) {
314 if (tol / fail_count < 0.04) {
315 return true;
316 }
317 }
318 return false;
319 }
320 return true;
321 }
322
323 /*
324 * compFp32WithTData: compare the data with the data in hisi .t file
325 * param:
326 * actualOutputData: the result of ge
327 * expectedDataFile: the path of hisi .t result file
328 * rtol:
329 * atol:
330 * return:
331 * true of false
332 * */
compFp32WithTData(float *actualOutputData, const std::string& expectedDataFile, float rtol = 1e-05, float atol = 1e-08, bool isquant = false)333 bool compFp32WithTData(float *actualOutputData, const std::string& expectedDataFile,
334 float rtol = 1e-05, float atol = 1e-08,
335 bool isquant = false) {
336 std::vector<int64_t> dim_info;
337 std::vector<int64_t>* ptr_dim_info = &dim_info;
338 float *expectedOutputData =
339 reinterpret_cast<float *>(readTestDataFile(expectedDataFile, ptr_dim_info));
340 uint32_t i = 0;
341 uint64_t data_size = 1;
342 data_size = accumulate(dim_info.begin(), dim_info.end(), 1, std::multiplies<uint64_t>());
343
344 // print caffe/tf output:
345 printf("[common.cpp] expected output data:");
346 for (; i < data_size && i < 10; i++) {
347 printf("%4f ", expectedOutputData[i]);
348 }
349 printf("\n");
350 if (isquant) {
351 bool ret = allclose(actualOutputData, expectedOutputData, data_size, rtol, atol,
352 true);
353 free(expectedOutputData);
354 return ret;
355 }
356 bool ret = allclose(actualOutputData, expectedOutputData, data_size, rtol, atol);
357 free(expectedOutputData);
358 return ret;
359 }
360
compUint8WithTData(uint8_t *actualOutputData, const std::string& expectedDataFile, float rtol = 1e-05, float atol = 1e-08, bool isquant = false)361 bool compUint8WithTData(uint8_t *actualOutputData, const std::string& expectedDataFile,
362 float rtol = 1e-05, float atol = 1e-08,
363 bool isquant = false) {
364 std::vector<int64_t> dim_info;
365 std::vector<int64_t>* ptr_dim_info = &dim_info;
366 auto dataFile = readTestDataFile(expectedDataFile, ptr_dim_info);
367 if(dataFile == nullptr){
368 return false;
369 }
370 uint8_t *expectedOutputData =
371 reinterpret_cast<uint8_t *>(dataFile);
372 uint32_t i = 0;
373 uint64_t data_size = 1;
374 data_size = accumulate(dim_info.begin(), dim_info.end(), 1, std::multiplies<uint64_t>());
375
376 // print caffe/tf output:
377 printf("\n [common.cpp] expected output data:\n");
378 for (; i < data_size && i < 10; i++) {
379 printf("%4hhu ", static_cast<unsigned char>(expectedOutputData[i]));
380 }
381 printf("\n");
382 if (isquant) {
383 bool ret = allclose_int8(actualOutputData, expectedOutputData, data_size, rtol,
384 atol, true);
385 free(expectedOutputData);
386 return ret;
387 }
388 bool ret = allclose_int8(actualOutputData, expectedOutputData, data_size, rtol,
389 atol);
390 free(expectedOutputData);
391 return ret;
392 }
393
394 /*
395 * ReadFile: read file of model
396 * param:
397 * file: file location
398 * size: file size
399 * return:
400 * buf of file
401 * */
ReadFile(const char *file, size_t* size)402 char *ReadFile(const char *file, size_t* size) {
403 printf("[common.cpp] Loading data from: %s\n", file);
404
405 std::ifstream ifs(file);
406 if (!ifs.good()) {
407 return nullptr;
408 }
409
410 if (!ifs.is_open()) {
411 ifs.close();
412 return nullptr;
413 }
414
415 ifs.seekg(0, std::ios::end);
416 *size = ifs.tellg();
417
418 char *buf = new char[*size];
419 if (buf == nullptr) {
420 ifs.close();
421 return nullptr;
422 }
423
424 ifs.seekg(0, std::ios::beg);
425 ifs.read(buf, *size);
426 ifs.close();
427 printf("[common.cpp]Read Binary Data Over, get tensorSize as: %" PRId64 ".\n", static_cast<int64_t>(*size));
428
429 return buf;
430 }
431
PackNCHWToNHWCFp32(const char *src, char *dst, int batch, int plane, int channel)432 void PackNCHWToNHWCFp32(const char *src, char *dst, int batch, int plane, int channel) {
433 for (int n = 0; n < batch; n++) {
434 for (int c = 0; c < channel; c++) {
435 for (int hw = 0; hw < plane; hw++) {
436 int nhwc_index = n * channel * plane + hw * channel + c;
437 int nchw_index = n * channel * plane + c * plane + hw;
438 dst[nhwc_index * 4] = src[nchw_index * 4];
439 dst[nhwc_index * 4 + 1] = src[nchw_index * 4 + 1];
440 dst[nhwc_index * 4 + 2] = src[nchw_index * 4 + 2];
441 dst[nhwc_index * 4 + 3] = src[nchw_index * 4 + 3];
442 }
443 }
444 }
445 return;
446 }
447
448
getTimeInUs()449 uint64_t getTimeInUs() {
450 const uint64_t MICROSECONDS_PER_SECOND = 1000000;
451 uint64_t time;
452 struct timeval tv;
453 gettimeofday(&tv, nullptr);
454 time = static_cast<uint64_t>(tv.tv_sec) * MICROSECONDS_PER_SECOND + tv.tv_usec;
455 return time;
456 }
457
CalculateIntVector(std::vector<float> vec)458 std::map<std::string, float> CalculateIntVector(std::vector<float> vec) {
459 float max = 0, min = FLT_MAX, sum = 0, avg;
460 for (auto v : vec) {
461 max = fmax(max, v);
462 min = fmin(min, v);
463 sum += v;
464 }
465 avg = vec.size() > 0 ? sum / vec.size() : 0;
466 std::map<std::string, float> result = {
467 {"MIN", min},
468 {"MAX", max},
469 {"AVG", avg},
470 {"SUM", sum}};
471 return result;
472 }
473
474