阶段性工作总结
本阶段完成 K3 AI 从 ONNX Runtime 调用入口、用户态运行时、内核设备通道到 FP16 算子后端的首轮贯通,并已完成一次 YOLOv5 FP16 推理与图片标注验证。
阶段成果
已建立从 ONNX 节点到 K3 内核任务的执行链路:Execution Provider 将可支持的节点转交给 K3
runtime,runtime 将节点描述和 tensor 元数据组织为图请求,通过 K3 AI runner 字符设备提交给
内核;内核调度器随后将任务派发到 k3_kernel_backend。提交、完成等待和资源回收均通过统一的
通道对象管理。
端到端链路已经完成一次 YOLOv5 FP16 推理与图片标注验证。输入图片经预处理后进入 ONNX Runtime 的 K3 Execution Provider;图任务在板端执行完成后,用户态完成输出解码、NMS 和标注图片生成。 该结果确认模型接入、任务提交、完成等待、结果回收和标注输出能够形成闭环。
后端现在以 FP16 为数值计算主路径,并按统一的静态入口分发。公共调用层仍将 AUTO target
归一化为 PREFER_A100,避免各算子对默认 target 作出不同解释;PREFER_CPU 用于软件参考实现。
但为 A100 bring-up,k3_kernel_backend/src/lib.rs 中的 k3_run_kernel 当前有一处临时 patch:
它忽略调度器传入的 target hint,统一改为 PREFER_A100,旁边已保留恢复原始 hint 的 TODO。
该 patch 用于让当前 FP16 模型默认在 A100 上执行,而不是验证 X100 路由;它不是长期的多 target
调度策略。完成 X100 路由和 target-specific dispatch 后,应恢复对调度器 target hint 的透传。
用户态运行时与 ABI
k3_aiRuntime/src/fronted/kd_uring.rs是用户态提交入口。build_channel建立共享内存和设备 通道,submit_graph提交图描述,wait_graph_complete等待完成事件;阅读调度链路时可从这 三个函数开始。k3_aiUabi/src/desc.rs、k3_aiUabi/src/kernel.rs和k3_aiUabi/src/kernelattr.rs定义内核与 用户态共用的描述符、属性、target hint 及 ioctl 相关 ABI。ABI 源码变更会反映到版本哈希,避免 新旧结构体混用造成静默错误。k3_aiRuntime/src/ort_ffi.rs是 ONNX Runtime K3 EP 与 runtime 的桥接层。它校验操作码、执行 目标、tensor 个数、shape、连续 stride 和字节数,再将请求转换为AiGraphNode。FFI 可传递 dense、连续的 tensor 元数据;但进入当前 backend 的数值 tensor 必须为 F16,不满足条件的请求 会在 backend 返回错误。ort_test提供端到端验证程序,可通过带 K3 EP 的 ONNX Runtime 执行 FP16 YOLOv5 推理并完成 图片标注。构建、交叉编译和部署说明见ort_test/README.md;本地 ONNX Runtime checkout 及其 CMake 产物不纳入版本控制。
ONNX Runtime 的 CPU EP 仍可承接 K3 EP 未声明支持的节点;但节点一旦已分配给 K3,执行期错误会 直接返回失败,不能将该节点作为失败重试再交回 CPU。因此排障时需要同时核对提交节点的操作码、 节点编号、target 和 backend 错误码。
算子后端
k3_kernel_backend/src/lib.rs 保留 C ABI 顶层入口,并定义 ComputeKernel。入口按 KernelOp
静态调用对应 marker 的 ComputeKernel::call;各 marker 再按 FP16 与 target 路由到具体实现,
不使用动态注册表。k3_kernel_backend/src/call.rs 集中处理通用 ABI、dense/strided 元数据、属性
读取、target 归一化和 F16 typed view 校验。
主要实现位于 binary.rs、unary.rs、matmul.rs、conv2d.rs、nn.rs 和 transform.rs;
rvv.rs 提供 FP16 路由所需的向量原语。A100 的 IME 只用于矩阵乘的 smt.vfwmadot:固定
8×8×8 tile,以 FP16 相乘、FP32 累加。IME 没有通用逐元素、exp、仿射或 sigmoid 指令,因此
可由 IME 替代的矩阵计算优先走 IME,其余密集 FP16 数值计算走 RVV。具体覆盖范围如下:
| 类别 | 已接入算子或能力 | 当前执行落点 |
|---|---|---|
| 矩阵乘 | MAT_MUL | F16 CPU reference 或 A100 FP16 IME smt.vfwmadot;X100 明确返回不支持 |
| 卷积 | CONV2D,含 group/depthwise 和可选 bias | 通用 im2col 后复用 MAT_MUL 的 A100 IME 路径。padding、stride、dilation、group 等通用几何关系不能由 IME slide 指令的固定偏移表示,因此不单独用 slide 指令替换 im2col |
| 逐元素与归一化 | ADD、SUB、MUL、DIV、SIGMOID、SILU、SCALE、RMS_NORM、ROPE | F16 decode → F32 RVV compute → F16 encode;CPU 保留 reference。SIGMOID、SILU 和 SCALE 也已使用 RVV,不再落到 CPU |
| 逐元素与归一化 | MOD | F16 decode → F32 scalar fmod → F16 encode;广播由 BroadcastPlan 校验 |
| 张量与布局变换 | CONCAT、TRANSPOSE、GATHER、GATHER_ELEMENTS、COPY、CAST、RESIZE、EXPAND、TILE | 连续搬运和索引访问优先使用 RVV copy/gather;布局、axis 和 shape 控制保持标量实现。数值数据使用 F16,Gather 索引支持 I32/I64,必要的 Cast 限制在 F16、I32 和 I64 |
| 常用网络算子 | MAX_POOL、REDUCE_MAX、TOP_K、SOFTMAX、GLU | 密集数值计算复用 RVV primitive;TopK 的选择/排序控制保持标量实现,TopK 和可选 MaxPool indices 输出为 I64 |
RVV 内联汇编中,vsetvli 写入的 VL 输出统一使用 out(reg),确保该输出不会与后续向量 load/store
使用的指针寄存器重叠,避免 f16_sigmoid_work 等路径因指针被 VL 覆盖而访问错误地址。
当前入口的 A100 临时 patch 会让模型中的 MatMul 和 Conv2D 稳定落到上述 A100 IME 路径,而不是
路由到 X100。恢复 scheduler target hint 后,PREFER_X100 仍只覆盖已有的 FP16 RVV 算子;其
MatMul 和 Conv2D 不会静默回退到 CPU,而是返回 UnsupportedOp,从而暴露尚未补齐的 X100 实现。
数值计算 tensor 只接受 F16。F32、BF16、I8、U8 及 ggml 量化 dtype 到达 backend 时返回
UnsupportedDtype;内部允许以 F32 完成累加或参考计算,但不构成 F32 tensor 执行路径。整数仅
保留给 Gather/GatherElements 的索引、TopK 与可选 MaxPool 的 indices 输出,以及受限的 Cast。
量化 ABI 仅保留兼容表面:AiQuantDesc、AiTensorDesc.quant、AiTensorLayout::GGML_QUANT、
量化 dtype 编号和 TensorManager::alloc_ggml_quant_tensor 继续保留,避免破坏外部结构布局与已有
分配接口。backend 已删除 ggml 执行、反量化、量化 MatMul、量化广播和行访问实现;GET_ROWS 与
SET_ROWS 已从属性、分发与实现中移除,操作码 25/26 保留为空洞。k3_kernel_backend/src/quant.rs
以及 LLaMA/ggml 相关测试和参考脚本已移除。
当前算子 backend 的职责是验证执行链路,并不是项目的长期核心。后续可直接切换到 K3 提供的计算 API;需要持续演进的核心仍是图任务、通道、worker、完成事件和核心绑定组成的调度系统。
内核设备与调度
板端支持仓库中的 os/StarryOS/kernel/src/pseudofs/dev/accelerator 新增 K3 AI runner 字符设备。
用户态通过 BUILD_CHANNEL 和 SUBMIT_GRAPH 两类 ioctl 建立通道并提交图;内核侧验证共享区、
登记图任务、唤醒调度器,并在完成后向用户态返回事件。调度日志保留 pid、token、节点编号及映射
后的算子名称,便于把用户态请求与内核执行结果对应起来。
K3 专属调度器以每个 A100 核心对应一个 worker 的方式组织任务。图执行完成、失败或被取消时会 更新节点状态、释放注册资源并通知等待方。与此同时,针对板端用户态取指异常和 cluster CPU 范围 补充了适配,减少跨 cluster 调度和页故障地址处理带来的不确定性。
USB 与 UVC 驱动
USB host 增加了类似 Linux USB ID table 的 interface 到驱动自动匹配机制,核心实现位于板端支持
仓库的 drivers/usb/usb-host/src/driver.rs。枚举完成后,USB core 根据 VID/PID、interface class、
subclass 和 protocol 生成匹配项,依次执行 driver probe;只有 probe 成功后才记录 interface 的
逻辑认领,并在设备断开时调用对应的 disconnect 生命周期。
基于该机制,uvcvideo 薄驱动已能发现并逻辑认领测试摄像头的 Video Control 和 Video Streaming
interface。摄像头的端口连接、描述符读取、interface 匹配和配置协商已验证;伪文件系统也已提供
video0 设备节点和基础 fd 操作接口。当前尚未得到完整视频帧,异步 live device ownership、
VC/VS 双 interface 管理、UVC format/frame descriptor 解析、等时 endpoint 配置和 payload 组帧
尚未接入完整生命周期。