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 if (fail_count != 0) {
169 printf("\n fabs(a[i] - b[i])/(fabs(b[i])+1) : %f\n",
170 tol / fail_count);
171 printf("\n fabs(a[i] - b[i]) : %f\n", tol1 / fail_count);
172 printf("\n fabs(a[i] - b[i])/fabs(b[i]) : %f\n", tol2 / fail_count);
173 }
174 c = c + count;
175 printf("\n avg : %f\n", sum / count);
176 printf("\n min : %f\n", minimum);
177 printf("\n max : %f\n", maximum);
178 printf("\n avg_all : %f\n", sum_all / c);
179 printf("\n");
180 fstream file;
181 file.open("cout.csv", ios::app);
182
183 file << ","
184 << "1,"
185 << "0," << maximum;
186 if (fail_count == 0) {
187 file << "," << sum_all / c;
188 } else {
189 file << "," << tol / fail_count;
190 }
191 file.close();
192 }
193 }
194 if (nan_occur_in_accuray) {
195 printf("\n[common.cpp] eval output include some NAN/INF\n");
196 return false;
197 }
198
199 if (fail_count > 0) {
200 printf("\n *** These data compare failed: atol = %f, rtol = %f\n", atol,
201 rtol);
202 printf("\n");
203 if (isquant) {
204 if (tol / fail_count < 0.04) {
205 return true;
206 }
207 }
208 return false;
209 }
210 return true;
211 }
212
allclose_int8(uint8_t * a,uint8_t * b,uint64_t count,float rtol=1e-05,float atol=1e-08,bool isquant=false)213 bool allclose_int8(uint8_t *a, uint8_t *b, uint64_t count, float rtol = 1e-05,
214 float atol = 1e-08, bool isquant = false) {
215 uint32_t i = 0;
216 // add fail loop print
217 uint32_t fail_count = 0;
218 float tol = 0;
219 float tol1 = 0;
220 float tol2 = 0;
221 bool nan_occur_in_accuray = false;
222
223 float sum = 0.0f;
224 static float sum_all;
225 static float maximum = 0;
226 static float minimum = 0;
227 static uint64_t c = 0;
228 // add fail loop print
229
230 if (a == nullptr || b == nullptr) {
231 return false;
232 }
233
234 for (; i < count; ++i) {
235 sum = sum + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
236 sum_all = sum_all + fabs(a[i] - b[i]) / (atol + rtol * fabs(b[i]));
237 maximum = max(static_cast<double>(maximum),
238 static_cast<double>(fabs(a[i] - b[i])) / (atol + rtol * fabs(b[i])));
239 minimum = min(static_cast<double>(minimum),
240 static_cast<double>(fabs(a[i] - b[i])) / (atol + rtol * fabs(b[i])));
241 if (isnan(a[i]) || isinf(a[i])) {
242 fail_count = fail_count + 1;
243 nan_occur_in_accuray = true;
244 if (fail_count < 100) {
245 printf(" i = %2u: %+f | %+f\n", i, static_cast<float>(a[i]), static_cast<float>(b[i]));
246 }
247 } else if (fabs(a[i] - b[i]) > 0) {
248 tol = tol + fabs(a[i] - b[i]) / (fabs(b[i]) + 1);
249 tol1 = tol1 + fabs(a[i] - b[i]);
250 tol2 = tol2 + fabs(a[i] - b[i]) / fabs(b[i]);
251 fail_count = fail_count + 1;
252 printf("%2d", static_cast<int>(fabs(a[i] - b[i])));
253 printf(" i = %2u: %2d | %2d\n", i, a[i], b[i]);
254 }
255 if (i == count - 1) {
256 printf(" ……\n");
257 printf("\n *** Total fail_count: %u\n", fail_count);
258 if (fail_count != 0) {
259 printf("\n fabs(a[i] - b[i])/(fabs(b[i])+1) : %f\n",
260 tol / fail_count);
261 printf("\n fabs(a[i] - b[i]) : %f\n", tol1 / fail_count);
262 printf("\n fabs(a[i] - b[i])/fabs(b[i]) : %f\n", tol2 / fail_count);
263 }
264
265 c = c + count;
266 printf("\n avg : %f\n", sum / count);
267 printf("\n min : %f\n", minimum);
268
269 printf("\n max : %f\n", maximum);
270 printf("\n avg_all : %f\n", sum_all / c);
271 printf("\n");
272 fstream file;
273 file.open("cout.csv", ios::app);
274
275 file << ","
276 << "1,"
277 << "0," << maximum;
278 if (fail_count == 0) {
279 file << "," << sum_all / c;
280 } else {
281 file << "," << tol / fail_count;
282 }
283 file.close();
284 }
285 }
286 if (nan_occur_in_accuray) {
287 printf("\n[common.cpp] eval output include some NAN/INF\n");
288 return false;
289 }
290 if (fail_count > 0) {
291 printf("\n *** These data compare failed: atol = %f, rtol = %f\n", atol,
292 rtol);
293 printf("\n");
294 if (isquant) {
295 if (tol / fail_count < 0.04) {
296 return true;
297 }
298 }
299 return false;
300 }
301 return true;
302 }
303
304 /*
305 * compFp32WithTData: compare the data with the data in hisi .t file
306 * param:
307 * actualOutputData: the result of ge
308 * expectedDataFile: the path of hisi .t result file
309 * rtol:
310 * atol:
311 * return:
312 * true of false
313 * */
compFp32WithTData(float * actualOutputData,const std::string & expectedDataFile,float rtol=1e-05,float atol=1e-08,bool isquant=false)314 bool compFp32WithTData(float *actualOutputData, const std::string& expectedDataFile,
315 float rtol = 1e-05, float atol = 1e-08,
316 bool isquant = false) {
317 std::vector<int64_t> dim_info;
318 std::vector<int64_t>* ptr_dim_info = &dim_info;
319 float *expectedOutputData =
320 reinterpret_cast<float *>(readTestDataFile(expectedDataFile, ptr_dim_info));
321 uint32_t i = 0;
322 uint64_t data_size = 1;
323 data_size = accumulate(dim_info.begin(), dim_info.end(), 1, std::multiplies<uint64_t>());
324
325 // print caffe/tf output:
326 printf("[common.cpp] expected output data:");
327 for (; i < data_size && i < 10; i++) {
328 printf("%4f ", expectedOutputData[i]);
329 }
330 printf("\n");
331 if (isquant) {
332 bool ret = allclose(actualOutputData, expectedOutputData, data_size, rtol, atol,
333 true);
334 free(expectedOutputData);
335 return ret;
336 }
337 bool ret = allclose(actualOutputData, expectedOutputData, data_size, rtol, atol);
338 free(expectedOutputData);
339 return ret;
340 }
341
compUint8WithTData(uint8_t * actualOutputData,const std::string & expectedDataFile,float rtol=1e-05,float atol=1e-08,bool isquant=false)342 bool compUint8WithTData(uint8_t *actualOutputData, const std::string& expectedDataFile,
343 float rtol = 1e-05, float atol = 1e-08,
344 bool isquant = false) {
345 std::vector<int64_t> dim_info;
346 std::vector<int64_t>* ptr_dim_info = &dim_info;
347 auto dataFile = readTestDataFile(expectedDataFile, ptr_dim_info);
348 if(dataFile == nullptr){
349 return false;
350 }
351 uint8_t *expectedOutputData =
352 reinterpret_cast<uint8_t *>(dataFile);
353 uint32_t i = 0;
354 uint64_t data_size = 1;
355 data_size = accumulate(dim_info.begin(), dim_info.end(), 1, std::multiplies<uint64_t>());
356
357 // print caffe/tf output:
358 printf("\n [common.cpp] expected output data:\n");
359 for (; i < data_size && i < 10; i++) {
360 printf("%4hhu ", static_cast<unsigned char>(expectedOutputData[i]));
361 }
362 printf("\n");
363 if (isquant) {
364 bool ret = allclose_int8(actualOutputData, expectedOutputData, data_size, rtol,
365 atol, true);
366 free(expectedOutputData);
367 return ret;
368 }
369 bool ret = allclose_int8(actualOutputData, expectedOutputData, data_size, rtol,
370 atol);
371 free(expectedOutputData);
372 return ret;
373 }
374
375 /*
376 * ReadFile: read file of model
377 * param:
378 * file: file location
379 * size: file size
380 * return:
381 * buf of file
382 * */
ReadFile(const char * file,size_t * size)383 char *ReadFile(const char *file, size_t* size) {
384 printf("[common.cpp] Loading data from: %s\n", file);
385
386 std::ifstream ifs(file);
387 if (!ifs.good()) {
388 return nullptr;
389 }
390
391 if (!ifs.is_open()) {
392 ifs.close();
393 return nullptr;
394 }
395
396 ifs.seekg(0, std::ios::end);
397 *size = ifs.tellg();
398
399 char *buf = new char[*size];
400 if (buf == nullptr) {
401 ifs.close();
402 return nullptr;
403 }
404
405 ifs.seekg(0, std::ios::beg);
406 ifs.read(buf, *size);
407 ifs.close();
408 printf("[common.cpp]Read Binary Data Over, get tensorSize as: %" PRId64 ".\n", static_cast<int64_t>(*size));
409
410 return buf;
411 }
412
PackNCHWToNHWCFp32(const char * src,char * dst,int batch,int plane,int channel)413 void PackNCHWToNHWCFp32(const char *src, char *dst, int batch, int plane, int channel) {
414 for (int n = 0; n < batch; n++) {
415 for (int c = 0; c < channel; c++) {
416 for (int hw = 0; hw < plane; hw++) {
417 int nhwc_index = n * channel * plane + hw * channel + c;
418 int nchw_index = n * channel * plane + c * plane + hw;
419 dst[nhwc_index * 4] = src[nchw_index * 4];
420 dst[nhwc_index * 4 + 1] = src[nchw_index * 4 + 1];
421 dst[nhwc_index * 4 + 2] = src[nchw_index * 4 + 2];
422 dst[nhwc_index * 4 + 3] = src[nchw_index * 4 + 3];
423 }
424 }
425 }
426 return;
427 }
428