Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第二周周报(6.9-6.15)

本周工作概览

本周到目前为止完成了四件事:

  • 完成用户态 backend 算子库的框架和 ABI,补出 matmul 算子的最小调用骨架。
  • 完成 buffer pin/map/cache 最小路径,用户库负责 tensor 的分配和管理,共享任务队列通过 airunner + ioctl + shared mmap 建立。
  • 完成 k3_airunner 的 BUILD_CHANNEL 最小通路,并在 k3_test 中验证共享内存保活是否成立。
  • 根据 K3 HMP 文档进一步确认 Linux 侧的 AI 核使用方式,明确后续需要补线程类型和核心亲和性控制接口。

buffer pin/map/cache 最小路径

目前的实现是:

  • tensor 的分配和生命周期先由用户态算子库承担;
  • 用来提交任务和接收执行结果的共享内存,不走普通堆内存,而是通过打开 airunner 后由用户先 mmap(MAP_SHARED | MAP_ANONYMOUS) 建立一片共享区;
  • 然后用户把这片共享区的信息通过 ioctl 交给内核;
  • 内核检查这段用户地址空间确实对应 shared backend 之后,抓住它背后的强引用做保活。

这样做以后,这片共享内存就可以稳定地拿来做无锁任务队列。

当前任务提交流程

现阶段整个任务提交流程还是偏传统外挂设备风格:

  • 打开设备文件
  • 通过 ioctl 建立通道
  • 后续继续通过 ioctl 或共享区提交任务

在 K3 上先这么做,不是因为 A100 只能这样用,而是为了后面多线程、多重型任务和多核心调度时,内核需要有一个统一的裁决点。这样后续做负载均衡、核心裁决和跨进程竞争控制时,路径是通的。

后面仍然会保留更轻的执行方式。后续会补一条更轻量的异步、纯用户态调度路径,把小任务、低冲突场景和直接用户态执行的效率保留下来。

k3_test 最小通路验证

这周已经在 k3_test 里把 BUILD_CHANNEL 最小链路跑通了。

当前测试过程是:

  1. 用户态调用 build_channel();
  2. 用户先 mmap 出共享区;
  3. k3_airunner 收到 ioctl 后验证这段共享区,并在内核里建立保活记录;
  4. 用户往共享区写入标记字符串;
  5. 用户态主动 drop 掉表层 UringChannel;
  6. 再次访问原共享区地址,确认数据还在;
  7. 再尝试 MAP_FIXED_NOREPLACE 到同一地址,确认原映射仍然占着这段地址范围。

当前运行日志如下:

root@starry:/root # ./k3_test
[ 70.972350 0:27 starry_kernel::pseudofs::dev::k3_airunner:60] k3_airunner: BUILD_CHANNEL ioctl reached, arg=0x3fffffb30
[ 70.973101 0:27 starry_kernel::pseudofs::dev::k3_airunner:119] k3_airunner: BUILD_CHANNEL keepalive pid=27, user_va=0x75000, size=0x10400, channels=2
[ 70.973589 0:27 starry_kernel::pseudofs::dev::k3_airunner:138] k3_airunner: BUILD_CHANNEL registered pid=27, va=0x75000, size=0x11000, pages=17
k3_test: channel built, va=0x75000, size=0x10400
k3_test: wrote marker string into shared channel memory
k3_test: dropped user-facing UringChannel handle
k3_test: readback after drop="ovchannel"
k3_test: MAP_FIXED_NOREPLACE failed as expected, original mapping is still occupying the same va range

这个结果说明当前共享区保活路径是成立的。用户态先放手之后,内核侧仍然能把这段共享区托住。

文档发现

K3 HMP

从这份文档里可以确认,Linux 上是通过线程类型和亲和性控制来做的。

当前公开路径里,Linux 侧是通过 /proc/set_ai_thread 把线程标记成 AI 线程,然后再由内核把它约束到 A100 核心集合上运行。这个是因为 X100 和 A100 的向量宽度不同,线程一旦开始使用对应的向量状态,就不能再随意跨类型迁移。