NPU异步推理警惕缓存旧值与超时后复用
偶发错帧经常只在连续异步推理中出现,单次调试却无法复现。使用NPU共享缓冲区时,必须同时解决新数据何时对设备可见,以及超时以后谁仍可能访问旧缓冲区,才能避免隐蔽的数据竞争。
在不具备完全硬件缓存一致性的平台上,主机写入输入后,最新内容可能仍停留在处理器缓存中,设备通过直接内存访问读到的却是旧值。对共享缓冲区的访问因此需要遵守平台定义的同步接口,把写入发布给设备;输出方向则应在设备完成之后,执行要求的可见性处理,再由主机读取。缓存清理和缓存失效并不是可以任意互换的动作,也不应在用户代码中凭经验拼接,应由驱动或运行时按映射属性实施。
完成通知解决的是依赖顺序,可见性操作解决的是哪个参与者能读到新内容。二者通常需要配合,不能因为拿到了一个完成事件,就假定所有缓存属性下都已经满足读取条件。Linux共享缓冲区接口也区分处理器访问同步与设备间栅栏;处理器访问的开始和结束,并不替应用排除其他参与者的并发访问。实际责任边界应从所用运行时的接口契约确认,若它已经封装同步,应用再重复维护缓存可能徒增开销甚至破坏使用约定。
一种容易审查的实现,是把每个缓冲区划分为可写、已提交、设备完成和可回收等状态,并让状态变迁与事件绑定。主机不能在已提交状态覆盖输入,后处理也不能在结果读取结束前归还输出。压力测试可给每次请求写入不同图案和递增序号,检查结果与请求是否对应;还应覆盖生产者快于消费者的情况。即使物理地址从未改变,逻辑所有权仍会随请求转换,固定地址不能证明不存在竞争。
当一次调用等待超时,最危险的错误是立即把缓冲区放回池中。超时只说明等待方没有在期限内得到完成结果,并不自动证明设备已经停止。设备可能仍在计算,也可能在稍后执行写回;若同一块内存已经交给下一次请求,迟到写入就会污染新结果。异常表现往往落在后一个请求上,使开发者误以为新模型或新输入有问题,实际故障起点却是前一个未被终止的任务。
因此,NPU超时恢复必须按平台提供的取消、排空或复位机制建立停止访问的证据。仅删除主机任务对象,未必会撤销已经下发的设备命令;仅收到取消请求受理,也不必然等于取消完成。回收条件应是相关任务已经完成,或者驱动确认设备不再访问这些映射。若无法获得这种保证,应隔离该任务占用的资源并限制继续提交,避免用无限新增缓冲区的办法暂时掩盖失控生命周期。
复位后还需防止迟到通知被误认成新任务完成。可以采用请求代次与设备会话标识,核对事件属于哪个执行周期;这种标识只用于识别事件,不能替代底层的停止访问保证。故障注入应覆盖正常完成与超时同时发生、取消期间进程退出以及复位后首次提交。每条路径都要验证映射、句柄和引用计数的释放顺序,确保既没有过早回收,也没有让已终止任务永久占用资源。
稳定的异步推理依赖清晰的所有权协议:正常路径证明数据已经可见,异常路径证明旧任务已经失去访问权。只有这两个条件成立,缓冲区复用才是安全的。





