netrans/bin/vxcode/template/vnn_loop.c

584 lines
16 KiB
C

/****************************************************************************
* Generated by NETRANS #NETRANS_VERSION#
* Match ovxlib #OVXLIB_VERSION#
*
* Neural Network application loop source file
****************************************************************************/
/*-------------------------------------------
Includes
-------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __linux__
#include <time.h>
#elif defined(_WIN32)
#include <windows.h>
#endif
#define _BASETSD_H
#include "vsi_nn_pub.h"
#include "vnn_global.h"
#include "vnn_loop.h"
/*-------------------------------------------
Types
-------------------------------------------*/
typedef struct
{
vsi_nn_tensor_attr_t attr;
uint8_t* data;
vsi_nn_size_t data_size; /* in bytes */
} vnn_internal_buffer_t;
/*-------------------------------------------
Macros and Variables
-------------------------------------------*/
#define VNN_CHECK_PTR( ptr, lbl, msg ) do {\
if( NULL == ptr ) {\
const char* message = msg ? msg : "None";\
const char* format = "Error: NULL pointer! %s: %s at %d, message: %s\n";\
printf(format, __FILE__, __FUNCTION__, __LINE__, message);\
goto lbl;\
}\
} while(0)
#define VNN_CHECK_STATUS( stat, lbl, msg ) do {\
if( VSI_SUCCESS != stat ) {\
const char* format = "Error: Status(%d) at %s:%s:%d";\
printf(format, (stat), __FILE__, __FUNCTION__, __LINE__);\
goto lbl;\
}\
} while(0)
/*-------------------------------------------
Functions
-------------------------------------------*/
/* internal buffer procedures */
vsi_status internal_buffer_init(vnn_internal_buffer_t* buffer, vsi_nn_tensor_t* tensor)
{
vsi_status status = VSI_FAILURE;
vsi_size_t element_num = 0;
vsi_size_t i = 0;
vsi_size_t stride = 0;
vsi_size_t data_size = 0;
uint8_t * data = NULL;
float default_value = 0.0f;
if( TRUE == tensor->attr.vtl )
{
VSILOGE("Internal tensors cannot be dumpped.\n");
return status;
}
if( NULL == buffer )
{
VSILOGE("Internal buffer is NULL.\n");
return status;
}
memcpy(&buffer->attr, &tensor->attr, sizeof(tensor->attr));
data_size = vsi_nn_GetTensorSize( buffer->attr.size, buffer->attr.dim_num, buffer->attr.dtype.vx_type );
element_num = vsi_nn_GetElementNum(tensor);
stride = (vsi_size_t)vsi_nn_TypeGetBytes( tensor->attr.dtype.vx_type );
data = (uint8_t *)malloc(data_size);
if( NULL == buffer )
{
printf("Out of memoery.\n");
goto error;
}
/* init data with zero */
for( i = 0; i < element_num; i++ )
{
status = vsi_nn_Float32ToDtype(default_value, data + i * stride, &buffer->attr.dtype);
VNN_CHECK_STATUS(status, error, "vsi_nn_Float32ToDtype fail");
}
buffer->data = data;
buffer->data_size = data_size;
error:
if( VSI_SUCCESS != status )
{
SAFE_FREE(data);
}
return status;
}
vsi_status internal_buffer_deinit(vnn_internal_buffer_t* buffer)
{
vsi_status status = VSI_FAILURE;
if( NULL == buffer )
{
VSILOGE("Internal buffer is NULL.\n");
return status;
}
SAFE_FREE(buffer->data);
return VSI_SUCCESS;
}
vsi_status internal_buffer_copy_to_tensor
(
vsi_nn_graph_t* graph,
vnn_internal_buffer_t* buffer,
vsi_nn_tensor_t* tensor
)
{
vsi_status status = VSI_FAILURE;
vsi_size_t request_data_size = 0;
if( NULL == buffer )
{
VSILOGE("Internal buffer is NULL.\n");
return status;
}
request_data_size = vsi_nn_GetTensorSize( tensor->attr.size, tensor->attr.dim_num, tensor->attr.dtype.vx_type );
if( request_data_size != buffer->data_size )
{
VSILOGE("Internal buffer size error.\n");
return status;
}
status = vsi_nn_CopyDataToTensor(graph, tensor, buffer->data);
return status;
}
static vsi_status internal_buffer_copy_from_tensor
(
vsi_nn_graph_t* graph,
vnn_internal_buffer_t* buffer,
vsi_nn_tensor_t* tensor
)
{
vsi_status status = VSI_FAILURE;
vsi_size_t request_data_size = 0;
uint8_t* data = NULL;
if( NULL == buffer )
{
VSILOGE("Internal buffer is NULL.\n");
return status;
}
request_data_size = vsi_nn_GetTensorSize( tensor->attr.size, tensor->attr.dim_num, tensor->attr.dtype.vx_type );
if( request_data_size != buffer->data_size )
{
VSILOGE("Internal buffer size error.\n");
return status;
}
data = vsi_nn_ConvertTensorToData( graph, tensor );
if(buffer->data && data)
{
memcpy(buffer->data, data, request_data_size);
status = VSI_SUCCESS;
}
VSI_SAFE_FREE(data);
return status;
}
/* internal buffer procedures end */
/* common procedures */
uint32_t load_bin_data
(
const char* fname,
uint8_t** buffer_ptr,
uint32_t* buffer_sz
)
{
FILE *fp = NULL;
uint32_t fsize = 0;
uint32_t read_size = 0;
uint8_t* buffer = NULL;
/* load data from file */
fp = fopen(fname, "rb");
if( !fp )
{
fsize = 0;
goto final;
}
fsize = fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
buffer = (uint8_t *)malloc(fsize);
fseek(fp, 0, SEEK_SET);
read_size = fread(buffer, 1, fsize, fp);
if(read_size != fsize)
{
fsize = 0;
free(buffer);
buffer = NULL;
goto final;
}
if(buffer_ptr != NULL)
{
*buffer_ptr = buffer;
}
if(buffer_sz != NULL)
{
*buffer_sz = read_size;
}
final:
if(!fsize)
{
printf("load data from %s fail!\n", fname);
}
if(fp)
{
fclose(fp);
}
return fsize;
}
uint32_t load_tensor_data_fp32
(
const char* fname,
uint8_t** buffer_ptr,
uint32_t* buffer_sz
)
{
float fval = 0.0;
uint32_t i = 0;
uint8_t* buffer = NULL;
uint32_t item_ount = 0;
uint32_t read_size = 0;
uint32_t stride = sizeof(fval);
FILE *fp = NULL;
fp = fopen(fname, "rb");
if( !fp )
{
read_size = 0;
goto final;
}
while(!feof(fp) && fscanf( fp, "%f ", &fval ) == 1)
{
item_ount++;
}
if( item_ount > 0 )
{
read_size = item_ount * stride;
buffer = (uint8_t *)malloc(read_size);
fseek(fp, 0, SEEK_SET);
for( i = 0; i < item_ount; i++ )
{
if(fscanf( fp, "%f ", &buffer[stride * i] ) != 1)
{
printf("Read tensor file fail.\n");
printf("Please check file lines or if the file contains illegal characters\n");
free(buffer);
goto final;
}
}
}
if(buffer_ptr != NULL)
{
*buffer_ptr = buffer;
}
if(buffer_sz != NULL)
{
*buffer_sz = read_size;
}
final:
if(!read_size)
{
printf("load data from %s fail!\n", fname);
}
if(fp)
{
fclose(fp);
}
return read_size;
}
vsi_status conditional_loop
(
vsi_nn_graph_t *graph,
prepare_input_data_func_type prepare_input_data_func,
process_output_data_func_type process_output_data_func,
void* user_data
)
{
vsi_nn_node_t* node;
vsi_nn_tensor_t* tensor;
vsi_status status = VSI_FAILURE;
vnn_internal_buffer_t* buffer_ptr = NULL; /* ptr to hold internal recurrent inputs/outputs */
uint32_t buffer_cnt = 0;
uint32_t curr_buffer_index = 0;
uint32_t i = 0, j = 0;
uint32_t iteration = 0;
uint32_t err_code = 0;
for( i = 0; i < graph->node_num; i ++ )
{
node = graph->nodes[i];
if( NULL != node )
{
switch(node->op)
{
case VSI_NN_OP_LSTMUNIT:
{
buffer_cnt += 2; /* cell state and h statue */
}
break;
case VSI_NN_OP_CONCATSHIFT:
{
buffer_cnt += 1;
}
break;
case VSI_NN_OP_SVDF:
{
buffer_cnt += 1;
}
break;
default:
break;
}
}
}
buffer_ptr = (vnn_internal_buffer_t *)malloc(buffer_cnt * sizeof(vnn_internal_buffer_t));
memset(buffer_ptr, 0x00, buffer_cnt * sizeof(vnn_internal_buffer_t));
/* malloc buffer */
for( i = 0; i < graph->node_num; i ++ )
{
node = graph->nodes[i];
if( NULL != node )
{
switch(node->op)
{
case VSI_NN_OP_LSTMUNIT:
{
/* h state in/out */
tensor = vsi_nn_GetTensor( graph, node->input.tensors[1] );
status = internal_buffer_init(&buffer_ptr[curr_buffer_index], tensor);
if( VSI_SUCCESS != status )
{
goto error_handling;
}
curr_buffer_index++;
/* cell state in/out */
tensor = vsi_nn_GetTensor( graph, node->input.tensors[2] );
status = internal_buffer_init(&buffer_ptr[curr_buffer_index], tensor);
if( VSI_SUCCESS != status )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
case VSI_NN_OP_CONCATSHIFT:
{
tensor = vsi_nn_GetTensor( graph, node->input.tensors[0] );
status = internal_buffer_init(&buffer_ptr[curr_buffer_index], tensor);
if( VSI_SUCCESS != status )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
case VSI_NN_OP_SVDF:
{
tensor = vsi_nn_GetTensor( graph, node->input.tensors[1] );
status = internal_buffer_init(&buffer_ptr[curr_buffer_index], tensor);
if( VSI_SUCCESS != status )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
default:
break;
}
}
}
while(!err_code)
{
printf("iteration %d...\n", iteration);
if(!prepare_input_data_func(graph, iteration, user_data))
{
/* No input data available */
printf("No input data available.\n");
break;
}
/* copy internal buffer in */
curr_buffer_index = 0;
for( i = 0; i < graph->node_num; i ++ )
{
node = graph->nodes[i];
if( NULL != node )
{
switch(node->op)
{
case VSI_NN_OP_LSTMUNIT:
{
/* h state in/out */
j = 1;
tensor = vsi_nn_GetTensor( graph, node->input.tensors[j] );
status = internal_buffer_copy_to_tensor( graph, &buffer_ptr[curr_buffer_index], tensor);
if( status == VSI_FAILURE )
{
goto error_handling;
}
curr_buffer_index++;
/* cell state in/out */
j = 2;
tensor = vsi_nn_GetTensor( graph, node->input.tensors[j] );
status = internal_buffer_copy_to_tensor( graph, &buffer_ptr[curr_buffer_index], tensor);
if( status == VSI_FAILURE )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
case VSI_NN_OP_CONCATSHIFT:
{
j = 0;
tensor = vsi_nn_GetTensor( graph, node->input.tensors[j] );
status = internal_buffer_copy_to_tensor( graph, &buffer_ptr[curr_buffer_index], tensor);
if( VSI_SUCCESS != status )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
case VSI_NN_OP_SVDF:
{
j = 1;
tensor = vsi_nn_GetTensor( graph, node->input.tensors[j] );
status = internal_buffer_copy_to_tensor( graph, &buffer_ptr[curr_buffer_index], tensor);
if( VSI_SUCCESS != status )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
default:
break;
}
}
}
/* process graph */
status = vsi_nn_RunGraph(graph);
/* save internal buffer */
curr_buffer_index = 0;
for( i = 0; i < graph->node_num; i++ )
{
node = graph->nodes[i];
if( NULL != node )
{
switch(node->op)
{
case VSI_NN_OP_LSTMUNIT:
{
/* h state in/out */
j = 1;
tensor = vsi_nn_GetTensor( graph, node->output.tensors[j] );
status = internal_buffer_copy_from_tensor(graph, &buffer_ptr[curr_buffer_index], tensor);
if( status == VSI_FAILURE )
{
goto error_handling;
}
curr_buffer_index++;
/* cell state in/out */
j = 2;
tensor = vsi_nn_GetTensor( graph, node->output.tensors[j] );
status = internal_buffer_copy_from_tensor(graph, &buffer_ptr[curr_buffer_index], tensor);
if( status == VSI_FAILURE )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
case VSI_NN_OP_CONCATSHIFT:
{
j = 1;
tensor = vsi_nn_GetTensor( graph, node->output.tensors[j] );
status = internal_buffer_copy_from_tensor(graph, &buffer_ptr[curr_buffer_index], tensor);
if( status == VSI_FAILURE )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
case VSI_NN_OP_SVDF:
{
j = 1;
tensor = vsi_nn_GetTensor( graph, node->output.tensors[j] );
status = internal_buffer_copy_from_tensor(graph, &buffer_ptr[curr_buffer_index], tensor);
if( status == VSI_FAILURE )
{
goto error_handling;
}
curr_buffer_index++;
}
break;
default:
break;
}
}
}
if(process_output_data_func)
{
if(!process_output_data_func(graph, iteration, user_data))
{
printf("Output condition reach.\n");
break;
}
}
iteration++;
}
error_handling:
for( i = 0; i < buffer_cnt; i++ )
{
internal_buffer_deinit(&buffer_ptr[i]);
}
SAFE_FREE(buffer_ptr);
return status;
}