18.3. 应用示例¶
18.3.1. 异步方式运行神经网络模型¶
#include <stdio.h>
#include <gx_dcache.h>
#include <gx_snpu.h>
#include "model.h" // NPU编译器生成的模型文件
#define MCU_TO_DEV(x) ((unsigned int)x & 0x0fffffff)
static float in_data[xxx]; // 模型输入数据
static struct input in __attribute__((aligned(DCACHE_LINE_SIZE)));
static struct output out __attribute__((aligned(DCACHE_LINE_SIZE)));
static int is_finished = 0;
// float32转换成short,snpu输入和输出是short类型数据,如果原始数据是float,需转换
// 详细可参考FAQ部分
static short float32_to_int16(float in_data, int Q)
{
int int_value = in_data * (1 << Q);
return (int_value > 32767) ? 32767 : ((int_value < -32768) ? -32768 : int_value);
}
static int gx_snpu_float32_to_int16(short *out_data, float *in_data, int Q, int num)
{
int i;
if (in_data == NULL || out_data == NULL) {
printf("[%s] error: para null\n", __FUNCTION__);
return -1;
}
for (i = 0; i < num; i++) {
out_data[i] = float32_to_int16(in_data[i], Q);
}
return 0;
}
// snpu异步任务运行完成后,会调用该回调函数
static int callback(void *private_data)
{
gx_dcache_invalid_range((void*)&out, sizeof(out)); // 获取snpu计算结果前,需刷cache
// 处理输出数据...
is_finished = 1;
return 0;
}
int main (int argc, char **argv)
{
gx_snpu_init(); // 初始化SNPU
int ret;
GX_SNPU_TASK task;
// 将model.h中的各个数组赋值给GX_SNPU_TASK结构体
task.data = (void*)MCU_TO_DEV(data_content);
task.cmd = (void*)MCU_TO_DEV(cmd_content);
task.weight = (void*)MCU_TO_DEV(weight_content);
task.cache = (void*)MCU_TO_DEV(cache_content);
task.input = (void*)MCU_TO_DEV(&in);
task.output = (void*)MCU_TO_DEV(&out);
gx_snpu_float32_to_int16((short*)&in.Feats, (float*)in_data, FEATS_Q, sizeof(in.Feats)/sizeof(short)); // SNPU只支持int16输入
gx_dcache_clean_range((void*)&in, sizeof(in)); // 数据给snpu使用前,需刷cache
ret = gx_snpu_run_task(&task, callback, NULL); // 异步方式运行模型
if (ret) {
printf("run task failed\n");
return -1;
}
while (is_finished == 0); // 等待模型运行完成
gx_snpu_exit(); // 退出SNPU
return 0;
}
18.3.2. 同步方式运行神经网络模型¶
#include <stdio.h>
#include <gx_dcache.h>
#include <gx_snpu.h>
#include "model.h" // NPU编译器生成的模型文件
#define MCU_TO_DEV(x) ((unsigned int)x & 0x0fffffff)
static float in_data[xxx]; // 模型输入数据
static struct input in __attribute__((aligned(DCACHE_LINE_SIZE)));
static struct output out __attribute__((aligned(DCACHE_LINE_SIZE)));
// float32转换成short,snpu输入和输出是short类型数据,如果原始数据是float,需转换
// 详细可参考FAQ部分
static short float32_to_int16(float in_data, int Q)
{
int int_value = in_data * (1 << Q);
return (int_value > 32767) ? 32767 : ((int_value < -32768) ? -32768 : int_value);
}
static int gx_snpu_float32_to_int16(short *out_data, float *in_data, int Q, int num)
{
int i;
if (in_data == NULL || out_data == NULL) {
printf("[%s] error: para null\n", __FUNCTION__);
return -1;
}
for (i = 0; i < num; i++) {
out_data[i] = float32_to_int16(in_data[i], Q);
}
return 0;
}
int main (int argc, char **argv)
{
gx_snpu_init(); // 初始化SNPU
int ret;
GX_SNPU_TASK task;
// 将model.h中的各个数组赋值给GX_SNPU_TASK结构体
task.data = (void*)MCU_TO_DEV(data_content);
task.cmd = (void*)MCU_TO_DEV(cmd_content);
task.weight = (void*)MCU_TO_DEV(weight_content);
task.cache = (void*)MCU_TO_DEV(cache_content);
task.input = (void*)MCU_TO_DEV(&in);
task.output = (void*)MCU_TO_DEV(&out);
gx_snpu_float32_to_int16((short*)&in.Feats, in_data, FEATS_Q, sizeof(in.Feats)/sizeof(short)); // SNPU只支持int16输入
gx_dcache_clean_range((void*)&in, sizeof(in)); // 数据给snpu使用前,需刷cache
ret = gx_snpu_run_task_sync(&task); // 同步方式运行模型
if (ret) {
printf("run task failed\n");
return -1;
}
gx_dcache_invalid_range((void*)&out, sizeof(out)); // 获取snpu计算结果前,需刷cache
gx_snpu_exit(); // 退出SNPU
return 0;
}