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;
}