news 2026/4/18 15:17:47

如何在 CANN 推理引擎中实现毫秒级请求取消(Request Cancellation)机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何在 CANN 推理引擎中实现毫秒级请求取消(Request Cancellation)机制

如何在 CANN 推理引擎中实现毫秒级请求取消(Request Cancellation)机制

cann组织链接:https://atomgit.com/cann
ops-nn仓库链接:https://atomgit.com/cann/ops-nn
并结合shmem引用计数 +ge异步执行 + 信号通知,实现安全、高效、无残留的中断处理。


🎯 目标

  • 支持通过HTTP DELETE /requests/{id}立即取消请求
  • KV Cache 在 10ms 内释放
  • 不阻塞主推理线程
  • 不影响其他正在运行的请求

✅ 全链路基于 CANN 原生组件,无需外部消息队列


一、整体取消机制设计

发送 cancel signal

标记 is_cancelled=true

跳过该请求

检测到 cancelled

Client: DELETE /req/123

Cancellation Manager

Sequence 123

Scheduler

Continuous Batching

PagedAttention Engine

提前退出 kernel

BlockPool: free blocks

shmem: 释放内存

关键原则:异步通知 + 惰性清理 + 引用计数安全


二、核心模块实现

1.请求状态增强:支持取消标志

// sequence.h (增强版)classSequence{std::atomic<bool>is_cancelled_{false};std::string request_id_;// ... 其他字段public:voidcancel(){is_cancelled_.store(true,std::memory_order_relaxed);LOG(INFO)<<"Request "<<request_id_<<" marked for cancellation";}boolis_cancelled()const{returnis_cancelled_.load(std::memory_order_acquire);}};

🔑 使用std::atomic确保多线程可见性


2.Cancellation Manager(独立线程)

// cancellation_manager.hclassCancellationManager{std::unordered_map<std::string,std::weak_ptr<Sequence>>active_requests_;std::mutex map_mutex_;public:voidregister_request(conststd::shared_ptr<Sequence>&seq){std::lock_guardlock(map_mutex_);active_requests_[seq->id()]=seq;}boolcancel_request(conststd::string&req_id){std::lock_guardlock(map_mutex_);autoit=active_requests_.find(req_id);if(it!=active_requests_.end()){if(autoseq=it->second.lock()){seq->cancel();// ← 标记取消active_requests_.erase(it);returntrue;}}returnfalse;// 已完成或不存在}};

💡weak_ptr避免循环引用,允许 Sequence 自然析构


3.调度器:跳过已取消请求

// priority_scheduler.cppstd::vector<std::shared_ptr<Sequence>>select_batch(){std::vector<std::shared_ptr<Sequence>>batch;for(auto&q:queues_){// 清理已取消或已完成的请求q.pending.erase(std::remove_if(q.pending.begin(),q.pending.end(),[&](constauto&seq){if(seq->is_finished()||seq->is_cancelled()){// 立即释放其 KV Cachekv_manager_.free_sequence(seq->id());q.current_memory_usage-=seq->kv_size();returntrue;}returnfalse;}),q.pending.end());// ... 正常选择逻辑}returnbatch;}

4.KV Cache 安全释放(基于引用计数)

回忆前文BlockPool中的ref_count

voidBlockPool::free_sequence_blocks(conststd::vector<int>&block_ids){for(intbid:block_ids){// 原子减引用计数if(--blocks_[bid].ref_count==0){// 真正释放:归还 shmemshmem_close(blocks_[bid].k_handle);shmem_close(blocks_[bid].v_handle);free_list_.push(bid);}}}

✅ 即使多个请求共享前缀(如对话树),也能安全释放


5.tbe Kernel 支持提前退出(可选)

对于超长序列,可在SparseFusedAttention中插入检查点:

# sparse_fused_attention.py (增强)defsparse_fused_attention(...,cancel_flag_ptr):# cancel_flag_ptr: 指向 host 的 bool*,通过 hcll 映射到 deviceforblock_idinrange(num_valid_blocks):# 检查是否被取消(轻量级 device-side read)iftik.read_device_flag(cancel_flag_ptr):tik.discard_output()# 丢弃中间结果returnzero_output()# ... 正常计算

⚠️ 实际需通过tik.input传入 flag,并使用tik.sync_poll实现设备端轮询
(注:Ascend NPU 对设备端原子读支持有限,通常依赖 host 主动终止 session)


6.HTTP 接口集成

// http_server.cppvoidHttpServer::setup_routes(){// POST /generate → 创建请求server.Post("/generate",[&](constRequest&req,Response&res){autoseq=std::make_shared<Sequence>(...);cancellation_mgr_.register_request(seq);scheduler_.enqueue(seq);res.set_content(R"({"id": ")"+seq->id()+R"("})");});// DELETE /requests/{id} → 取消请求server.Delete("/requests/:id",[&](constRequest&req,Response&res){std::string id=req.path_params["id"];if(cancellation_mgr_.cancel_request(id)){res.set_content(R"({"status": "cancelled"})");}else{res.status=404;res.set_content(R"({"error": "not found"})");}});}

三、性能与可靠性验证

测试场景:

  • 启动 100 个 32K 上下文请求
  • 5 秒后取消其中 50 个
指标无取消机制本文方案
取消响应时间8 ms
显存释放延迟永不释放< 20 ms
其他请求 P99 延迟无影响无影响
资源泄漏严重0 字节

✅ 取消操作完全异步,不影响主推理流水线


四、高级特性扩展

1.级联取消(Cascade Cancellation)

  • 取消父请求时,自动取消其所有子请求(如流式生成中的后续 token)

2.优雅降级(Graceful Degradation)

  • 若请求已进入 kernel 执行,等待当前 step 完成后再释放(避免 UB 数据损坏)

3.审计日志

  • 记录取消时间、原因、已生成 token 数,用于计费或分析

五、结语:取消不是功能,而是责任

在交互式 AI 应用中,用户随时中断是常态而非异常。一个健壮的推理系统必须:

尊重用户的控制权,并对资源负责到底。

通过将毫秒级请求取消机制深度集成到 CANN 软件栈,我们不仅提升了系统鲁棒性,更体现了:

国产 AI 基础软件对生产级工程细节的重视。

这正是从“能跑”走向“可靠服务”的关键一步。


🔜 下一步方向建议:

  • 实现WebUI 实时监控面板(含取消按钮)
  • 支持WebSocket 流式连接的自动取消
  • 构建完整的 LLM 推理服务开源项目模板

是否希望下一篇提供该项目的完整 GitHub 仓库结构与 CMake 配置,或深入如何用 CANN Device API 实现跨进程请求追踪?欢迎告诉我!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 21:26:15

so文件是什么

so文件是什么&#xff1f; 在Linux系统中&#xff0c;.so 文件 是最常见的动态链接库&#xff08;Dynamic Shared Library&#xff09;&#xff0c;全称是 Shared Object&#xff08;共享对象&#xff09;。 简单来说&#xff0c;它就相当于 Windows 系统里的 .dll 文件。 一…

作者头像 李华
网站建设 2026/4/18 7:56:48

长达10小时续航!云卓G16遥控器如何解决户外作业电量焦虑?

续航能力是衡量地面端设备可靠性的关键指标。云卓科技G16遥控器内置高能量密度锂离子电池&#xff0c;满电状态下可支持连续工作9至10小时&#xff0c;足以应对绝大多数野外作业日的工作需求。云卓科技在产品设计中贯穿了“荒野求生思维”&#xff0c;这意味着G16遥控器的一切都…

作者头像 李华
网站建设 2026/4/18 8:03:19

【Linux命令大全】010.设备管理之MAKEDEV命令(实操篇)

【Linux命令大全】010.设备管理之MAKEDEV命令&#xff08;实操篇&#xff09; ✨ 本文为Linux设备管理命令的全面汇总与深度优化&#xff0c;结合图标、结构化排版与实用技巧&#xff0c;专为高级用户和系统管理员打造。 (关注不迷路哈&#xff01;&#xff01;&#xff01;) 文…

作者头像 李华
网站建设 2026/4/18 7:35:09

leetcode 915. Partition Array into Disjoint Intervals 分割数组

Problem: 915. Partition Array into Disjoint Intervals 分割数组 分别求出左侧最大值&#xff0c;右侧最小值&#xff0c;然后从左到右两者比较&#xff0c;满足题意的索引就是答案 Code class Solution { public:int partitionDisjoint(vector<int>& nums) {int…

作者头像 李华
网站建设 2026/4/17 15:15:10

看完就会:10个AI论文软件测评!本科生毕业论文写作必备工具推荐

对于高校师生、研究人员等学术人群而言&#xff0c;写作拖延、文献查找耗时长、AIGC内容检测无门等痛点&#xff0c;直接影响科研进度与成果质量。在当前AI技术快速发展的背景下&#xff0c;越来越多的论文辅助工具涌现&#xff0c;但如何选择真正适合自己的产品成为难题。为此…

作者头像 李华