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