• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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