推理 API 参考(rknn_api.h)

来源:test/starrynpu/demo/yolov8/3rdparty/rknpu2/include/rknn_api.h 以下资料均来着StarryOS或社区收集。大多数暂未经过验证!。


一、类型定义

1.1 上下文句柄

#ifdef __arm__
typedef uint32_t rknn_context;
#else
typedef uint64_t rknn_context;

所有 API 围绕 rknn_context 句柄操作,内部指向闭源库维护的不透明状态。

1.2 错误码

常量说明
RKNN_SUCC0成功
RKNN_ERR_FAIL-1通用失败
RKNN_ERR_TIMEOUT-2执行超时
RKNN_ERR_DEVICE_UNAVAILABLE-3设备不可用
RKNN_ERR_MALLOC_FAIL-4内存分配失败
RKNN_ERR_PARAM_INVALID-5参数无效
RKNN_ERR_MODEL_INVALID-6模型无效
RKNN_ERR_CTX_INVALID-7上下文无效
RKNN_ERR_INPUT_INVALID-8输入无效
RKNN_ERR_OUTPUT_INVALID-9输出无效
RKNN_ERR_DEVICE_UNMATCH-10设备不匹配(需更新 SDK/驱动)
RKNN_ERR_INCOMPATILE_PRE_COMPILE_MODEL-11预编译模型不兼容
RKNN_ERR_INCOMPATILE_OPTIMIZATION_LEVEL_VERSION-12优化级别版本不兼容
RKNN_ERR_TARGET_PLATFORM_UNMATCH-13目标平台不匹配

1.3 张量类型

typedef enum _rknn_tensor_type {
    RKNN_TENSOR_FLOAT32 = 0,
    RKNN_TENSOR_FLOAT16,      // 1
    RKNN_TENSOR_INT8,         // 2
    RKNN_TENSOR_UINT8,        // 3
    RKNN_TENSOR_INT16,        // 4
    RKNN_TENSOR_UINT16,       // 5
    RKNN_TENSOR_INT32,        // 6
    RKNN_TENSOR_UINT32,       // 7
    RKNN_TENSOR_INT64,        // 8
    RKNN_TENSOR_BOOL,         // 9
    RKNN_TENSOR_INT4,         // 10
    RKNN_TENSOR_BFLOAT16,     // 11
} rknn_tensor_type;

1.4 量化类型

typedef enum _rknn_tensor_qnt_type {
    RKNN_TENSOR_QNT_NONE = 0,              // 无量化
    RKNN_TENSOR_QNT_DFP,                   // 动态定点(fractional length)
    RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC,     // 非对称仿射(zero_point + scale)
} rknn_tensor_qnt_type;

1.5 数据格式

typedef enum _rknn_tensor_format {
    RKNN_TENSOR_NCHW = 0,
    RKNN_TENSOR_NHWC,
    RKNN_TENSOR_NC1HWC2,    // NPU 原生格式
    RKNN_TENSOR_UNDEFINED,
} rknn_tensor_format;

1.6 核心掩码

typedef enum _rknn_core_mask {
    RKNN_NPU_CORE_AUTO   = 0,       // 自动选择
    RKNN_NPU_CORE_0      = 1,       // 核心 0
    RKNN_NPU_CORE_1      = 2,       // 核心 1
    RKNN_NPU_CORE_2      = 4,       // 核心 2
    RKNN_NPU_CORE_0_1    = 3,       // 核心 0+1 联合
    RKNN_NPU_CORE_0_1_2  = 7,       // 三核联合
    RKNN_NPU_CORE_ALL    = 0xffff,  // 平台自动选择多核
} rknn_core_mask;

1.7 初始化标志

标志说明逆向推断的内部行为
RKNN_FLAG_PRIOR_HIGH0x0高优先级(默认)设置 nice -19
RKNN_FLAG_PRIOR_MEDIUM0x1中优先级
RKNN_FLAG_PRIOR_LOW0x2低优先级
RKNN_FLAG_ASYNC_MASK0x4异步模式rknn_outputs_get 返回上一帧结果
RKNN_FLAG_COLLECT_PERF_MASK0x8性能采集启用逐层计时,降低帧率
RKNN_FLAG_MEM_ALLOC_OUTSIDE0x10外部内存分配用户负责分配 weight/internal/IO 内存
RKNN_FLAG_SHARE_WEIGHT_MEM0x20权重共享多上下文共享同一权重内存
RKNN_FLAG_FENCE_IN_OUTSIDE0x40外部输入 fence传入 DMA fence fd
RKNN_FLAG_FENCE_OUT_OUTSIDE0x80外部输出 fence获取 DMA fence fd
RKNN_FLAG_COLLECT_MODEL_INFO_ONLY0x100仅采集模型信息不实际加载,仅查询 weight/internal 大小
RKNN_FLAG_INTERNAL_ALLOC_OUTSIDE0x200外部分配内部内存
RKNN_FLAG_EXECUTE_FALLBACK_PRIOR_DEVICE_GPU0x400GPU 回退NPU 不支持的算子回退 GPU(OpenCL)
RKNN_FLAG_ENABLE_SRAM0x800启用 SRAM尝试在 SRAM 分配缓冲
RKNN_FLAG_SHARE_SRAM0x1000共享 SRAM多上下文共享 SRAM
RKNN_FLAG_DISABLE_PROC_HIGH_PRIORITY0x2000禁用高优先级不设置 nice -19
RKNN_FLAG_DISABLE_FLUSH_INPUT_MEM_CACHE0x4000禁用输入 cache flush用户自行保证 cache 一致性
RKNN_FLAG_DISABLE_FLUSH_OUTPUT_MEM_CACHE0x8000禁用输出 cache flush输出由 GPU/RGA 消费时使用
RKNN_FLAG_MODEL_BUFFER_ZERO_COPY0x10000模型缓冲零拷贝模型数据由 NPU 直接访问

二、核心结构体

2.1 张量属性 rknn_tensor_attr

typedef struct _rknn_tensor_attr {
    uint32_t index;                        // 输入/输出索引
    uint32_t n_dims;                       // 维度数
    uint32_t dims[RKNN_MAX_DIMS];          // 维度数组(最多 16 维)
    char     name[RKNN_MAX_NAME_LEN];      // 张量名(最长 256)
    uint32_t n_elems;                      // 元素总数
    uint32_t size;                         // 字节大小
    rknn_tensor_format fmt;                // 数据格式(NCHW/NHWC/NC1HWC2)
    rknn_tensor_type   type;               // 数据类型
    rknn_tensor_qnt_type qnt_type;         // 量化类型
    int8_t   fl;                           // DFP 小数位长度
    int32_t  zp;                           // 仿射量化零点
    float    scale;                        // 仿射量化缩放因子
    uint32_t w_stride;                     // 宽度方向步长(只读)
    uint32_t size_with_stride;             // 含步长的字节大小
    uint8_t  pass_through;                 // 直通模式标志
    uint32_t h_stride;                     // 高度方向步长(只写)
} rknn_tensor_attr;

2.2 张量内存 rknn_tensor_mem

typedef struct _rknn_tensor_memory {
    void*    virt_addr;     // 虚拟地址
    uint64_t phys_addr;     // 物理地址
    int32_t  fd;            // DMA buffer fd
    int32_t  offset;        // 内存偏移
    uint32_t size;          // 缓冲大小
    uint32_t flags;         // 标志
    void*    priv_data;     // 私有数据(闭源库内部使用)
} rknn_tensor_mem;

逆向推断priv_data 内部指向闭源库维护的 rknpu_mem_create 返回的 obj_addr,用于后续 mem_destroymem_sync 操作。

2.3 查询命令 rknn_query_cmd

命令返回结构体说明
RKNN_QUERY_IN_OUT_NUM0rknn_input_output_num输入/输出数量
RKNN_QUERY_INPUT_ATTR1rknn_tensor_attr输入张量属性
RKNN_QUERY_OUTPUT_ATTR2rknn_tensor_attr输出张量属性
RKNN_QUERY_PERF_DETAIL3rknn_perf_detail逐层性能(需 PERF_MASK)
RKNN_QUERY_PERF_RUN4rknn_perf_run推理总耗时
RKNN_QUERY_SDK_VERSION5rknn_sdk_versionSDK/驱动版本
RKNN_QUERY_MEM_SIZE6rknn_mem_size权重/内部内存大小
RKNN_QUERY_CUSTOM_STRING7rknn_custom_string自定义字符串
RKNN_QUERY_NATIVE_INPUT_ATTR8rknn_tensor_attr原生输入属性(NC1HWC2)
RKNN_QUERY_NATIVE_OUTPUT_ATTR9rknn_tensor_attr原生输出属性
RKNN_QUERY_DEVICE_MEM_INFO12设备内存信息
RKNN_QUERY_INPUT_DYNAMIC_RANGE13rknn_input_range动态 shape 范围
RKNN_QUERY_CURRENT_INPUT_ATTR14rknn_tensor_attr当前输入 shape(动态模型)
RKNN_QUERY_CURRENT_OUTPUT_ATTR15rknn_tensor_attr当前输出 shape(动态模型)

三、函数签名与逆向还原

3.1 生命周期管理

rknn_init

int rknn_init(rknn_context* context, void* model, uint32_t size, uint32_t flag, rknn_init_extend* extend);
参数说明
context[out] 上下文句柄指针
modelsize > 0 时为模型数据指针;size = 0 时为模型文件路径
size模型数据大小(0 表示从文件加载)
flag初始化标志组合(见 1.7)
extend扩展信息(可选,含 real_model_offsetmodel_buffer_fd 等)

逆向还原的内部流程

rknn_init()
├── 1. 打开 /dev/dri/card* 或 /dev/rknpu(获取 fd)
├── 2. ioctl(ACTION, RKNPU_GET_HW_VERSION) → 检查硬件版本
├── 3. 解析 .rknn 模型文件头
│   ├── 提取网络拓扑(层数、连接关系)
│   ├── 提取权重数据
│   └── 提取预编译命令流(如果是 pre-compile 模型)
├── 4. ioctl(MEM_CREATE) × N → 分配权重/内部/IO 内存
│   ├── 权重内存(RKNPU_MEM_KERNEL_MAPPING)
│   ├── 内部中间缓冲
│   └── 命令流缓冲(regcmd)
├── 5. ioctl(MEM_MAP) + mmap() → 映射到用户空间
├── 6. 将权重数据拷贝到 DMA 内存(转换为 native layout)
├── 7. 编译模型 → 生成寄存器命令流
│   ├── 为每层生成 NPUOP 指令序列
│   ├── 计算 CBUF bank 分配
│   └── 生成 Task 数组
├── 8. 如果 flag & RKNN_FLAG_PRIOR_HIGH → ioctl(ACTION, RKNPU_SET_PROC_NICE)
└── 9. 返回 context 句柄

rknn_destroy

int rknn_destroy(rknn_context context);

逆向还原

rknn_destroy()
├── 1. 释放所有 Task 数组内存
├── 2. munmap() + ioctl(MEM_DESTROY) × N → 释放所有 DMA 内存
├── 3. close(drm_fd)
└── 4. 释放上下文结构体

rknn_dup_context

int rknn_dup_context(rknn_context* context_in, rknn_context* context_out);

复制上下文,新上下文与原上下文共享权重内存(RKNN_FLAG_SHARE_WEIGHT_MEM 语义)。


3.2 推理流程

rknn_inputs_set

int rknn_inputs_set(rknn_context context, uint32_t n_inputs, rknn_input inputs[]);

逆向还原

rknn_inputs_set()
├── 1. 遍历 inputs[]
│   ├── 如果 pass_through == TRUE → 直接拷贝到输入 DMA 内存
│   └── 如果 pass_through == FALSE →
│       ├── 格式转换(NHWC → NCHW 或 NC1HWC2)
│       ├── 类型转换(FP32 → INT8/FP16,应用 scale/zp)
│       └── 拷贝到输入 DMA 内存
└── 2. ioctl(MEM_SYNC, SYNC_TO_DEVICE) → flush cache

rknn_run

int rknn_run(rknn_context context, rknn_run_extend* extend);
参数说明
extend->frame_id[out] 当前帧 ID
extend->non_block0=阻塞,1=非阻塞
extend->timeout_ms阻塞模式超时(毫秒)
extend->fence_fd外部 fence fd

逆向还原(核心路径):

rknn_run()
├── 1. 构造 rknpu_submit 结构体
│   ├── flags = RKNPU_JOB_PC | RKNPU_JOB_BLOCK(或 NONBLOCK)| RKNPU_JOB_PINGPONG
│   ├── task_obj_addr = tasks DMA 对象地址
│   ├── core_mask = 根据 rknn_set_core_mask() 设置
│   ├── subcore_task[] = 根据多核切分策略填充
│   └── timeout = extend->timeout_ms 或默认值
├── 2. ioctl(DRM_IOCTL_RKNPU_SUBMIT, &submit)
│   └── 内核驱动:
│       ├── 分配 job → 调度到核心
│       ├── 写 PC 寄存器(base_addr, amount, task_control, op_enable)
│       ├── 等待中断
│       └── 写回 task[].int_status
└── 3. 如果阻塞模式 → 等待 ioctl 返回
    如果非阻塞 → 立即返回,后续 rknn_wait() 或 rknn_outputs_get() 等待

rknn_wait

int rknn_wait(rknn_context context, rknn_run_extend* extend);

等待非阻塞推理完成。内部轮询或等待 fence 信号。

rknn_outputs_get

int rknn_outputs_get(rknn_context context, uint32_t n_outputs, rknn_output outputs[], rknn_output_extend* extend);

逆向还原

rknn_outputs_get()
├── 1. 如果异步模式 → 返回上一帧结果(不等待当前帧)
├── 2. ioctl(MEM_SYNC, SYNC_FROM_DEVICE) → invalidate output cache
├── 3. 遍历 outputs[]
│   ├── 如果 want_float == TRUE →
│   │   ├── 反量化(INT8 → FP32,应用 scale/zp)
│   │   └── 格式转换(NC1HWC2 → NCHW/NHWC)
│   ├── 如果 is_prealloc == TRUE → 拷贝到用户提供的 buf
│   └── 如果 is_prealloc == FALSE → 分配 buf 并拷贝
└── 4. extend->frame_id = 当前帧 ID

rknn_outputs_release

int rknn_outputs_release(rknn_context context, uint32_t n_ouputs, rknn_output outputs[]);

释放 rknn_outputs_getis_prealloc == FALSE 时分配的 buf。


3.3 查询接口

rknn_query

int rknn_query(rknn_context context, rknn_query_cmd cmd, void* info, uint32_t size);

通用查询接口。info 指向对应结构体,size 为结构体大小。

关键查询结构体

typedef struct _rknn_input_output_num {
    uint32_t n_input;
    uint32_t n_output;
} rknn_input_output_num;

typedef struct _rknn_perf_detail {
    char*    perf_data;      // 性能数据字符串(闭源库内部分配)
    uint64_t data_len;
} rknn_perf_detail;

typedef struct _rknn_perf_run {
    int64_t run_duration;    // 推理耗时(微秒)
} rknn_perf_run;

typedef struct _rknn_sdk_version {
    char api_version[256];
    char drv_version[256];
} rknn_sdk_version;

typedef struct _rknn_mem_size {
    uint32_t total_weight_size;
    uint32_t total_internal_size;
    uint64_t total_dma_allocated_size;
    uint32_t total_sram_size;
    uint32_t free_sram_size;
    uint32_t reserved[10];
} rknn_mem_size;

3.4 多核控制

rknn_set_core_mask

int rknn_set_core_mask(rknn_context context, rknn_core_mask core_mask);

逆向推断:设置后续 rknn_run 提交时 rknpu_submit.core_mask 的值。对于联合核心模式(CORE_0_1CORE_0_1_2),闭源库内部会将 Task 数组切分到 subcore_task[] 中。

rknn_set_batch_core_num

int rknn_set_batch_core_num(rknn_context context, int core_num);

设置批量推理时使用的核心数。


3.5 动态 Shape

rknn_set_input_shapes

int rknn_set_input_shapes(rknn_context ctx, uint32_t n_inputs, rknn_tensor_attr attr[]);

设置所有输入张量的 shape。仅对动态 shape 模型有效。调用后闭源库内部会重新编译命令流。

rknn_set_input_shape(已废弃)

int rknn_set_input_shape(rknn_context ctx, rknn_tensor_attr* attr);

3.6 扩展结构体

rknn_init_extend

typedef struct _rknn_init_extend {
    rknn_context ctx;
    int32_t      real_model_offset;    // 模型文件内偏移(零拷贝模式)
    uint32_t     real_model_size;      // 模型实际大小
    int32_t      model_buffer_fd;      // 模型缓冲 fd
    uint32_t     model_buffer_flags;   // 模型缓冲标志
    uint8_t      reserved[112];
} rknn_init_extend;

rknn_run_extend

typedef struct _rknn_run_extend {
    uint64_t frame_id;       // [out] 帧 ID
    int32_t  non_block;      // 0=阻塞,1=非阻塞
    int32_t  timeout_ms;     // 超时(毫秒)
    int32_t  fence_fd;       // 外部 fence fd
} rknn_run_extend;

rknn_output_extend

typedef struct _rknn_output_extend {
    uint64_t frame_id;       // [out] 输出对应的帧 ID
} rknn_output_extend;