Skip to content

Commit 8700dd8

Browse files
author
Siyuan Cheng
committed
example: add cifar10 example to mli module
add cifar10 example to mli module Signed-off-by: Siyuan Cheng <[email protected]>
1 parent 179a2cf commit 8700dd8

31 files changed

+14803
-0
lines changed
Lines changed: 397 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,397 @@
1+
/*
2+
* Copyright 2019-2022, Synopsys, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-3-Clause license found in
6+
* the LICENSE file in the root directory of this source tree.
7+
*
8+
*/
9+
#include "examples_aux.h"
10+
11+
#include <assert.h>
12+
#include <stdlib.h>
13+
14+
#include "mli_api.h"
15+
#include "idx_file.h"
16+
#include "tensor_transform.h"
17+
18+
/*
19+
* Find maximum value in the whole tensor and return it's argument (index)
20+
* Tensor data considered as linear array. Index corresponds to number of element in this array
21+
*/
22+
static inline int arg_max(mli_tensor * net_output_);
23+
24+
/*
25+
* Return label (int) stored in label container.
26+
* Function casts label_container_ to appropriate type,
27+
* according to type_ and return it's value as integer
28+
* It returns -1 if type is unknown.
29+
*/
30+
static inline int get_label(void * label_container_, enum tIdxDataType type_);
31+
32+
static FAST_TYPE(int32_t) pred_label = 0;
33+
34+
/* -------------------------------------------------------------------------- */
35+
/* Single vector processing for debug */
36+
/* -------------------------------------------------------------------------- */
37+
enum test_status model_run_single_in(const void *data_in, const float *ref_out,
38+
mli_tensor *model_input,
39+
mli_tensor *model_output, preproc_func_t preprocess,
40+
model_inference_t inference, const char *inf_param)
41+
{
42+
enum test_status ret_val = TEST_PASSED;
43+
size_t output_elements = mli_hlp_count_elem_num(model_output, 0);
44+
45+
float * pred_data = malloc(output_elements * sizeof(float));
46+
if (pred_data == NULL) {
47+
printf("ERROR: Can't allocate memory for output\n");
48+
return TEST_NOT_ENOUGH_MEM;
49+
}
50+
51+
// Data preprocessing and model inference
52+
preprocess(data_in, model_input);
53+
inference(inf_param);
54+
55+
// Check result
56+
if (MLI_STATUS_OK == mli_hlp_fx_tensor_to_float(model_output, pred_data, output_elements)) {
57+
struct ref_to_pred_output err;
58+
measure_err_vfloat(ref_out, pred_data, output_elements, &err);
59+
printf("Result Quality: S/N=%-10.1f (%-4.1f db)\n", err.ref_vec_length / err.noise_vec_length, err.ref_to_noise_snr);
60+
} else {
61+
printf("ERROR: Can't transform out tensor to float\n");
62+
ret_val = TEST_SUIT_ERROR;
63+
}
64+
free(pred_data);
65+
return ret_val;
66+
}
67+
68+
/* Multiple inputs from IDX file processing. Writes output for each tensor into output file */
69+
enum test_status model_run_idx_base_to_idx_out(const char *input_idx_path,
70+
const char *output_idx_path,
71+
mli_tensor *model_input, mli_tensor *model_output,
72+
preproc_func_t preprocess, model_inference_t inference,
73+
const char *inf_param)
74+
{
75+
enum test_status ret_val = TEST_PASSED;
76+
struct tIdxDescr descr_in = {0, 0, 0, NULL};
77+
struct tIdxDescr descr_out = {0, 0, 0, NULL};
78+
uint32_t shape[4] = {0, 0, 0, 0};
79+
void * input_data = NULL;
80+
float * output_data = NULL;
81+
size_t output_elements = mli_hlp_count_elem_num(model_output, 0);
82+
size_t input_elements = mli_hlp_count_elem_num(model_input, 0);
83+
84+
// Step 1: Resources preparations
85+
//================================================
86+
//Open and check input file
87+
if ((descr_in.opened_file = fopen(input_idx_path, "rb")) == NULL ||
88+
(idx_file_check_and_get_info(&descr_in)) != IDX_ERR_NONE ||
89+
descr_in.num_dim != model_input->rank + 1) {
90+
printf("ERROR: Problems with input idx file format.\n Requirements:\n"
91+
"\t tensor rank must be equal to model input rank + 1\n");
92+
ret_val = TEST_SUIT_ERROR;
93+
goto free_ret_lbl;
94+
}
95+
96+
// Read test base shape
97+
descr_in.num_elements = 0;
98+
if (idx_file_read_data(&descr_in, NULL, shape) != IDX_ERR_NONE) {
99+
printf("ERROR: Can't read input file shape\n");
100+
ret_val = TEST_SUIT_ERROR;
101+
goto free_ret_lbl;
102+
}
103+
104+
// Check compatibility between shapes of idx file and model input
105+
printf("IDX test file shape: [");
106+
for (int i = 0; i < descr_in.num_dim; i++) printf("%d,", shape[i]);
107+
printf("]\nModel input shape: [");
108+
for (int i = 0; i < model_input->rank; i++) printf("%d,", model_input->shape[i]);
109+
printf("]\n\n");
110+
for (int i = 1; i < descr_in.num_dim; i++)
111+
if ( shape[i] != model_input->shape[i-1]) {
112+
printf("ERROR: Shapes mismatch.\n");
113+
ret_val = TEST_SUIT_ERROR;
114+
goto free_ret_lbl;
115+
}
116+
117+
// Memory allocation for input/output (for it's external representations)
118+
input_data = malloc((input_elements * data_elem_size(descr_in.data_type)) + (output_elements * sizeof(float)));
119+
output_data = (float *)((char*)input_data + input_elements * data_elem_size(descr_in.data_type));
120+
if (input_data == NULL) {
121+
printf("ERROR: Can't allocate memory for input and output\n");
122+
ret_val = TEST_NOT_ENOUGH_MEM;
123+
goto free_ret_lbl;
124+
}
125+
126+
// Open output file
127+
if ( (descr_out.opened_file = fopen(output_idx_path, "wb")) == NULL) {
128+
printf("ERROR: Can't open output idx file\n");
129+
ret_val = TEST_SUIT_ERROR;
130+
goto free_ret_lbl;
131+
}
132+
133+
134+
// Step 2: Process vectors from input file one-by-another
135+
//================================================
136+
descr_out.data_type = IDX_DT_FLOAT_4B;
137+
descr_out.num_dim = model_output->rank + 1;
138+
uint32_t test_idx = 0;
139+
for (; test_idx < shape[0]; test_idx++) {
140+
// Get next input vector from file
141+
descr_in.num_elements = input_elements;
142+
if (idx_file_read_data(&descr_in, input_data, NULL) != IDX_ERR_NONE) {
143+
printf("ERROR: While reading test vector %u\n", test_idx);
144+
ret_val = TEST_SUIT_ERROR;
145+
goto free_ret_lbl;
146+
}
147+
148+
// Model inference for the vector
149+
preprocess(input_data, model_input);
150+
inference(inf_param);
151+
152+
// Output results to idx file
153+
descr_out.num_elements = output_elements;
154+
if (mli_hlp_fx_tensor_to_float(model_output, output_data, output_elements) != MLI_STATUS_OK ||
155+
idx_file_write_data(&descr_out, (const void *)output_data) != IDX_ERR_NONE) {
156+
printf("ERROR: While writing result for test vector %u\n", test_idx);
157+
ret_val = TEST_SUIT_ERROR;
158+
goto free_ret_lbl;
159+
}
160+
161+
// Notify User on progress (10% step)
162+
if (test_idx % (shape[0] / 10) == 0)
163+
printf("%10u of %u test vectors are processed\n", test_idx, shape[0]);
164+
}
165+
166+
// Step 3: Fill output file header and free resources
167+
//==================================================
168+
shape[0] = test_idx;
169+
for (int i = 0; i < model_output->rank; i++)
170+
shape[i+1] = model_output->shape[i];
171+
if (idx_file_write_header(&descr_out, shape) != IDX_ERR_NONE) {
172+
printf("ERROR: While final header writing of test out file \n");
173+
ret_val = TEST_SUIT_ERROR;
174+
}
175+
176+
free_ret_lbl:
177+
if (input_data != NULL)
178+
free(input_data);
179+
if (descr_in.opened_file != NULL)
180+
fclose(descr_in.opened_file);
181+
if (descr_out.opened_file != NULL)
182+
fclose(descr_out.opened_file);
183+
return ret_val;
184+
}
185+
186+
/* -------------------------------------------------------------------------- */
187+
/* Multiple inputs from IDX file processing. Calculate accuracy */
188+
/* -------------------------------------------------------------------------- */
189+
enum test_status model_run_acc_on_idx_base(
190+
const char * input_idx_path,
191+
const char * labels_idx_path,
192+
mli_tensor * model_input,
193+
mli_tensor * model_output,
194+
preproc_func_t preprocess,
195+
model_inference_t inference,
196+
const char * inf_param) {
197+
enum test_status ret = TEST_PASSED;
198+
struct tIdxDescr descr_in = {0, 0, 0, NULL};
199+
struct tIdxDescr descr_labels = {0, 0, 0, NULL};
200+
#ifdef _C_ARRAY_
201+
struct tIdxArrayFlag t_labels = { 0, LABELS };
202+
struct tIdxArrayFlag t_tests = { 0, TESTS };
203+
#endif
204+
uint32_t shape[4] = {0, 0, 0, 0};
205+
uint32_t labels_total = 0;
206+
uint32_t labels_correct = 0;
207+
int label = 0;
208+
size_t input_elements = mli_hlp_count_elem_num(model_input, 0);
209+
void * input_data = NULL;
210+
211+
/* Step 1: Resources preparations */
212+
/* Open and check input labels file */
213+
#ifndef _C_ARRAY_
214+
if ((descr_labels.opened_file = fopen(labels_idx_path, "rb")) == NULL ||
215+
(idx_file_check_and_get_info(&descr_labels)) != IDX_ERR_NONE ||
216+
descr_labels.data_type == IDX_DT_FLOAT_4B ||
217+
descr_labels.data_type == IDX_DT_DOUBLE_8B ||
218+
descr_labels.num_dim != 1) {
219+
printf("ERROR: Problems with labels idx file format.\n Requirements:\n"
220+
"\t Non-float format\n"
221+
"\t 1 dimensional tensor\n"
222+
);
223+
ret = TEST_SUIT_ERROR;
224+
goto free_ret_lbl;
225+
}
226+
227+
/* Read labels shape */
228+
descr_labels.num_elements = 0;
229+
if (idx_file_read_data(&descr_labels, NULL, shape) != IDX_ERR_NONE) {
230+
printf("ERROR: Problems with input idx file format.\n Requirements:\n"
231+
"\t tensors shape must be [N], where N is amount of tests)\n");
232+
ret = TEST_SUIT_ERROR;
233+
goto free_ret_lbl;
234+
}
235+
labels_total = shape[0];
236+
#else
237+
/* Open and check input labels file */
238+
array_file_check_and_get_info(&descr_labels, &t_labels);
239+
/* Read labels shape */
240+
array_file_read_data(&descr_labels, NULL, shape, &t_labels);
241+
labels_total = shape[0];
242+
#endif
243+
244+
/* Open and check input test idxfile */
245+
#ifndef _C_ARRAY_
246+
if ((descr_in.opened_file = fopen(input_idx_path, "rb")) == NULL ||
247+
(idx_file_check_and_get_info(&descr_in)) != IDX_ERR_NONE ||
248+
descr_in.num_dim != model_input->rank + 1) {
249+
printf("ERROR: Problems with input idx file format.\n Requirements:\n"
250+
"\t tensor rank must be equal to model input rank + 1\n");
251+
ret = TEST_SUIT_ERROR;
252+
goto free_ret_lbl;
253+
}
254+
255+
// Read test base shape
256+
descr_in.num_elements = 0;
257+
if (idx_file_read_data(&descr_in, NULL, shape) != IDX_ERR_NONE) {
258+
printf("ERROR: Can't read input file shape\n");
259+
ret = TEST_SUIT_ERROR;
260+
goto free_ret_lbl;
261+
}
262+
#else
263+
/* Open and check input test idxfile */
264+
array_file_check_and_get_info(&descr_in, &t_tests);
265+
266+
/* Read test base shape */
267+
array_file_read_data(&descr_in, NULL, shape, &t_tests);
268+
#endif
269+
// Check compatibility between shapes of idx file and model input
270+
printf("IDX test file shape: [");
271+
for (int i = 0; i < descr_in.num_dim; i++) printf("%d,", shape[i]);
272+
printf("]\nModel input shape: [");
273+
for (int i = 0; i < model_input->rank; i++) printf("%d,", model_input->shape[i]);
274+
printf("]\n\n");
275+
for (int i = 1; i < descr_in.num_dim; i++)
276+
if (shape[i] != model_input->shape[i-1]) {
277+
printf("ERROR: Shapes mismatch.\n");
278+
ret = TEST_SUIT_ERROR;
279+
goto free_ret_lbl;
280+
}
281+
282+
if (shape[0] != labels_total) {
283+
printf("ERROR: Amount of labels(%d) and test inputs(%d) are not the same\n", labels_total, shape[0]);
284+
ret = TEST_SUIT_ERROR;
285+
goto free_ret_lbl;
286+
}
287+
288+
// Memory allocation for raw input
289+
input_data = malloc(input_elements * data_elem_size(descr_in.data_type));
290+
if (input_data == NULL) {
291+
printf("ERROR: Can't allocate memory for input\n");
292+
ret = TEST_NOT_ENOUGH_MEM;
293+
goto free_ret_lbl;
294+
}
295+
296+
// Step 2: Process vectors from input file one-by-another
297+
//================================================
298+
uint32_t test_idx = 0;
299+
for (; test_idx < labels_total; test_idx++) {
300+
// Get next input vector from file and related label
301+
descr_in.num_elements = input_elements;
302+
descr_labels.num_elements = 1;
303+
#ifndef _C_ARRAY_
304+
if (idx_file_read_data(&descr_in, input_data, NULL) != IDX_ERR_NONE ||
305+
idx_file_read_data(&descr_labels, (void *)&label, NULL) != IDX_ERR_NONE) {
306+
printf("ERROR: While reading idx files content #%u\n", test_idx);
307+
ret = TEST_SUIT_ERROR;
308+
goto free_ret_lbl;
309+
}
310+
#else
311+
/* read from input data */
312+
array_file_read_data(&descr_in, input_data, NULL, &t_tests);
313+
/* read from label */
314+
array_file_read_data(&descr_labels, (void *)&label, NULL, &t_labels);
315+
#endif
316+
label = get_label(&label, descr_labels.data_type);
317+
318+
// Model inference
319+
preprocess(input_data, model_input);
320+
inference(inf_param);
321+
322+
labels_correct += (arg_max(model_output) == label)? 1: 0;
323+
324+
// Notify User on progress (10% step)
325+
if (((test_idx+1) % (labels_total / 10)) == 0)
326+
printf("%10u of %u test vectors are processed (%u are correct: %.3f %%)\n",
327+
test_idx+1, labels_total, labels_correct, (labels_correct*100.f)/(test_idx+1));
328+
}
329+
printf("Final Accuracy: %.3f %% (%u are correct of %u)\n",
330+
(labels_correct*100.f)/test_idx, labels_correct, labels_total);
331+
332+
// Step 3: Fill output file header and free resources
333+
//==================================================
334+
free_ret_lbl:
335+
if (input_data != NULL)
336+
free(input_data);
337+
if (descr_in.opened_file != NULL)
338+
fclose(descr_in.opened_file);
339+
if (descr_labels.opened_file != NULL)
340+
fclose(descr_labels.opened_file);
341+
return ret;
342+
}
343+
344+
/* -------------------------------------------------------------------------- */
345+
/* Internal routines */
346+
/* -------------------------------------------------------------------------- */
347+
348+
/* -------------------------------------------------------------------------- */
349+
/* Find argument (index) of maximum value in tensor */
350+
/* -------------------------------------------------------------------------- */
351+
static inline int arg_max(mli_tensor * net_output_) {
352+
353+
const mli_argmax_cfg argmax_cfg = {
354+
/* axis = */ -1,
355+
/* topk = */ 1
356+
};
357+
358+
mli_tensor out_tensor = { 0 };
359+
out_tensor.data.mem.pi32 = (int32_t *)&pred_label;
360+
out_tensor.data.capacity = sizeof(pred_label);
361+
out_tensor.el_type = MLI_EL_SA_32;
362+
out_tensor.rank = 2;
363+
out_tensor.shape[0] = 1;
364+
out_tensor.shape[1] = 1;
365+
out_tensor.mem_stride[0] = 1;
366+
out_tensor.mem_stride[1] = 1;
367+
368+
if (net_output_->el_type == MLI_EL_SA_8)
369+
mli_krn_argmax_sa8(net_output_, &argmax_cfg, &out_tensor);
370+
else
371+
mli_krn_argmax_fx16(net_output_, &argmax_cfg, &out_tensor);
372+
373+
return pred_label;
374+
}
375+
376+
//=================================================
377+
// Label type cast
378+
//=================================================
379+
static inline int get_label(void * label_container_, enum tIdxDataType type_) {
380+
switch(type_) {
381+
case IDX_DT_UBYTE_1B:
382+
return (int)*((unsigned char *)label_container_);
383+
384+
case IDX_DT_BYTE_1B:
385+
return (int)*((char *)label_container_);
386+
387+
case IDX_DT_SHORT_2B:
388+
return (int)*((short*)label_container_);
389+
390+
case IDX_DT_INT_4B:
391+
return (int)*((int*)label_container_);
392+
393+
default:
394+
return -1;
395+
}
396+
return -1;
397+
}

0 commit comments

Comments
 (0)