Prhub

#28287 [HiCache] Optimize HiCache hash generation with bulk token byte conversion

原始 PR 作者 huangtingwei9988 合并时间 2026-07-01 15:44 文件变更 7 提交数 8 评论 7 代码增减 +676 / -181

执行摘要

将 HiCache L3 哈希生成从 Python per-token 循环改为 C++ native 扩展,实现约 70× 加速

原有的哈希生成中,每个 page 的哈希通过 Python 循环 for t in token_ids: hasher.update(t.to_bytes(4, byteorder="little", signed=False)) 计算,当 HiCache L3 需要为大量 page 计算哈希时开销很大。该 PR 旨在通过 C++ 原生扩展来消除 per-token Python 调用,大幅提升哈希生成性能。

值得精读。该 PR 展示了一种典型的热点路径优化模式:识别 Python 循环瓶颈,通过 C++ 扩展和 AVX2 指令集大幅加速,同时保持 Python 调用的便利性。设计决策中关于 per-page scratch buffer 的使用、bigram 重叠对的生成、以及优先利用已有 array 缓冲区避免额外拷贝的思想,值得在其他性能敏感模块中借鉴。

讨论亮点

review 主要由 gemini-code-assist[bot] 提出两条中等优先级建议:

1) 使用 Union[str, List[str]] 代替 str | List[str] 以兼容 Python <3.10;
2) 使用 itertools.chain.from_iterable 优化嵌套生成器。
但这两个建议未被作者采纳,最终 PR 仍保留了 str | List[str] 和嵌套生成器写法,由 xiezhq-hermann 批准合并。

实现拆解

  1. 新增 C++ 扩展hash_binding.cpp):提供核心哈希例程,支持 regular 和 bigram 模式,使用 AVX2 指令加速 uint64 到 uint32 的转换,并通过 per-page scratch buffer 避免额外内存分配。
  2. 新增 Python 包装native_hash.py):检测平台兼容性(仅支持 little-endian Linux),通过 torch.utils.cpp_extension.load 在运行时编译加载扩展,提供 _native_hash_input 函数预处理输入数据(支持 array、列表、tuple bigram、EAGLE bigram 等格式),最终调用 C++ 的 get_hash 函数。
  3. 重构调用方:修改 utils.py 中的 get_hash_str 函数,新增 page_size 参数并委托给 get_native_hash;修改 radix_cache.py 中的 TreeNode.hash_page 方法,改为调用 get_hash_str;修改 cache_controller.pyhybrid_cache_controller.py 中的 _storage_hit_query 方法,利用批量哈希批处理减少 Python 循环。
  4. 配套测试:在 test_mem_cache_utils.py 中添加了 _legacy_get_hash_str_legacy_page_hashes 函数作为参考实现,并通过 _HashKey 辅助类构造了多种输入(plain list、array('I')array('q')、bigram 等),遍历单哈希和页面哈希的兼容性用例,确保新实现与旧实现输出完全一致。
文件 模块 状态 重要度
python/sglang/srt/mem_cache/cpp_utils/native_hash.py 哈希引擎 added 8.72
python/sglang/srt/mem_cache/cpp_utils/hash_binding.cpp 哈希引擎 added 7.98
python/sglang/srt/mem_cache/utils.py 缓存工具 modified 7.03
python/sglang/srt/mem_cache/radix_cache.py Radix 缓存 modified 6.34
python/sglang/srt/managers/cache_controller.py 缓存控制器 modified 5.49
python/sglang/srt/mem_cache/hybrid_cache/hybrid_cache_controller.py 混合缓存 modified 5.34
test/registered/unit/mem_cache/test_mem_cache_utils.py 测试 modified 7.52

关键符号

get_hash_str get_native_hash _native_hash_input TreeNode.hash_page CacheController._storage_hit_query compute_node_hash_values

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

关于 Python 版本兼容性使用 Union 的建议 style

gemini-code-assist[bot] 指出,在没有 `from __future__ import annotations` 的情况下,使用 `str | List[str]` 作为返回类型在 Python <3.10 中会运行时错误,建议改用 `Union[str, List[str]]`。同时建议使用 `itertools.chain.from_iterable` 替代嵌套生成器以提升性能。

结论:作者未采纳建议,PR 仍保留 `str | List[str]` 和嵌套生成器写法,由 xiezhq-hermann 批准合并。 · 已解决

风险与影响

1) C++ 扩展依赖 OpenSSL 的 -lcrypto 及 pybind11,在国内环境或某些 Docker 镜像下可能导致编译失败。
2) 仅支持 little-endian Linux 系统,其他平台(如 macOS、Windows)会抛出 RuntimeError。
3) 哈希算法虽然逻辑一致,但新实现必须保证与旧实现的精确输出一致,以免导致缓存 miss 或数据不一致。测试中已通过 _legacy_get_hash_str 进行了兼容性验证,但生产环境下仍可能存在边缘 case。
4) 新扩展通过 torch.utils.cpp_extension.load 在运行时编译,可能引入首次调用时的延迟。

直接提升 HiCache L3 哈希生成性能约 70×,降低缓存查询开销。对系统其余部分无影响。所有调用方均在内部委托给新实现,对外 API 保持向后兼容(get_hash_str 新增了可选参数 page_size)。测试覆盖了单页面哈希和批量页面哈希的兼容性。

编译依赖 OpenSSL/pybind11 仅限 little-endian Linux 首次编译延迟 哈希一致性需验证

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论