Skip to content

Develop/fix int64#927

Open
xinfei-shi wants to merge 2 commits intomainfrom
develop/fix_int64
Open

Develop/fix int64#927
xinfei-shi wants to merge 2 commits intomainfrom
develop/fix_int64

Conversation

@xinfei-shi
Copy link
Copy Markdown
Collaborator

@xinfei-shi xinfei-shi commented Apr 23, 2026

  • fix cache key type from int64_t -> uint64_t
  • fix request id type from int64_t -> uint64_t

@xinfei-shi xinfei-shi requested a review from LLLLKKKK as a code owner April 23, 2026 09:31
@LLLLKKKK
Copy link
Copy Markdown
Collaborator

🤖 AI Code Review — PR #927

PR 概述

Title: Develop/fix int64
Author: xinfei-shi
规模: 119(GitHub) files, +564/-501

核心目标

request_id 的类型从 int64_t 改为 uint64_t,将 CacheKeyTypeint64_t 改为 uint64_t,并将相关类型定义抽取到独立的 BasicType.h 头文件中。同时将 Types.h 重命名为 CacheTypes.h 以避免命名歧义。


改动逻辑拆解

GitHub 开源仓库变更(主要代码)

1. 类型定义重构(cache/BasicType.h, CacheTypes.h)

  • 新增 BasicType.h,集中定义 CacheKeyType = uint64_tBlockIdxType = int32_tGroupIdType = int32_tLayerIdsType
  • Types.h 重命名为 CacheTypes.h,移除原有的 GroupIdType/LayerIdsType 定义,改为 include BasicType.h
  • KVCacheResource.h 中原有的 CacheKeyType = int64_tBlockIdxType = int32_t 定义被移除,改为 include BasicType.h

2. request_id 类型变更(int64_t -> uint64_t)

  • GenerateInput::request_idGenerateOutputs::request_id 改为 uint64_t
  • GenerateStream::streamId() 返回类型改为 uint64_t
  • EmbeddingInput::request_idEmbeddingStream::streamId() 改为 uint64_t
  • API 层(ChatService、InferenceService、AccessLogWrapper、Exception)全链路跟随变更
  • RPC 层(GenerateContext、PrefillGenerateContext、DecodeRpcServer、LocalRpcServer)全链路跟随变更
  • P2P connector 全链路跟随变更

3. CacheKeyType 类型变更(int64_t -> uint64_t)

  • LayerCacheBufferblock_id_map_std::map<int64_t, int> 改为 std::map<CacheKeyType, int>
  • KeyBlockInfo::cache_keyint64_t 改为 CacheKeyType
  • ComputedLayerCacheBufferStore::computed_buffers_unordered_map<int64_t, ...> 改为 unordered_map<uint64_t, ...>

4. Proto 变更

  • model_rpc_service.protorequest_id 字段从 int64 改为 uint64(涉及多个 message)
  • cache_keys 字段从 repeated int64 改为 repeated uint64
  • CacheStatusPB::cache_keysmap<int64, bool> 改为 map<uint64, bool>
  • tcp_service.protoTcpCacheKeyBlockBufferInfo::keyint64 改为 uint64

5. 日志格式修正

  • 所有 %ld/%d 格式化 request_id/streamId() 的地方改为 %llu + (unsigned long long) cast

6. 兼容性桥接(RemoteConnector)

  • 新增 cacheKeysAsInt64Vec() 函数,通过 reinterpret_cast<const std::vector<int64_t>&>CacheKeysType 转为 vector<int64_t> 传给 MetaClient

7. 测试更新

  • 所有涉及 request_idcache_key 的测试用例同步更新类型声明

Checklist 检查结果

通用原则

软件工程原则

检查项 结果
SRP ✅ PR 聚焦于类型变更
OCP
LSP
ISP
DIP
DRY ✅ 类型定义集中到 BasicType.h
KISS
YAGNI

架构审视

检查项 结果
抽象边界 ✅ BasicType.h 作为底层类型定义层合理
依赖方向
状态完整性
错误语义
可观测性 ✅ 日志格式已同步更新
可演进性 ❌ Proto 字段类型变更是 breaking change(见问题 1)
可运维性 ❌ 缺少滚动升级兼容方案(见问题 1)

测试

检查项 结果
新功能有对应测试 ✅ 已有测试同步更新
边界 case 覆盖 ❌ 缺少 uint64_t 高位值(>INT64_MAX)的测试(见问题 3)

代码质量与文档

检查项 结果
无关改动分离 ❌ 混入了大量纯格式化对齐改动(见问题 5)
Commit 原子性 ✅ 两个 commit 分别处理 request_id 和 cache_key
PR description ❌ 过于简略,未说明动机(见问题 6)

领域检查

A. 兼容性与配置

检查项 结果
1.1 Breaking Change ❌ Proto int64->uint64 是 wire-format breaking change(见问题 1)
1.2 默认值变更 ✅ request_id 默认值从 -1 改为 0,合理

B. 正确性与逻辑

检查项 结果
逻辑错误 cacheKeysAsInt64Vec 的 reinterpret_cast 是 UB(见问题 2)
边界 case ❌ hash 值 int64->uint64 cast 可能改变 cache 匹配行为(见问题 3)
1.55 接口返回类型变更 streamId() 返回类型变更影响所有子类(见问题 4)

C. 线程安全与并发 — 全部 ✅

D. 性能 — 全部 ✅

E. 分式 — 全部 ✅

F. 跨平台 — 全部 ✅

G. 语言与框架特有 — 全部 ✅

H. 测试与 CI — 全部 ✅

I. 代码质量 — ❌ 格式化改动与功能改动混合(见问题 5)


Review 意见

问题

  1. Proto wire-format 兼容性:int64 -> uint64 是 breaking change [P0]

    Protobuf 的 int64 使用 varint 编码(ZigZag),而 uint64 使用 plain varint 编码。两者的 wire format 不同:同一个正整数值,int64uint64 编码后的字节序列不同。这意味着:

    • 旧版本客户端(使用 int64 request_id)发送的消息,新版本服务端(使用 uint64 request_id)解析时会得到错误的值
    • 滚动升级期间 prefill/decode 节点版本不一致时,RPC 通信会出现数据错误
    • CacheStatusPB::cache_keysmap<int64, bool> 改为 map<uint64, bool> 同理

    涉及文件:model_rpc_service.prototcp_service.proto

    建议

    • 方案 A:保持 proto 中的 int64 不变,仅在 C++ 层做 static_cast<uint64_t>(pb.request_id())。Proto 是跨进程接口,类型变更需要极其谨慎
    • 方案 B:如果确实需要改 proto,需要新增字段(如 uint64 request_id_v2 = N)并保留旧字段做 fallback
  2. cacheKeysAsInt64Vec 的 reinterpret_cast 是未定义行为 [P1]

    inline const std::vector<int64_t>& cacheKeysAsInt64Vec(const CacheKeysType& keys) {
        static_assert(sizeof(CacheKeyType) == sizeof(int64_t));
        return reinterpret_cast<const std::vector<int64_t>&>(keys);
    }

    reinterpret_caststd::vector<uint64_t>std::vector<int64_t> 之间转换违反 strict aliasing rule,是 C++ 标准中的未定义行为。虽然在实践中大多数编译器/平台上能工作,但编译器优化(特别是 LTO)可能基于 strict aliasing 假设产生错误代码。

    文件:RemoteConnector.cc

    建议:显式拷贝转换,或者保持 MetaClient 接口侧的 CacheKeysTypeint64_t

  3. hash 值从 int64_t cast 到 uint64_t 可能改变 cache 匹配行为 [P1]

    blockUtil.cchashInt64Vector 返回 int64_t,现在被 static_cast<CacheKeyType> 转为 uint64_t。如果现有已缓存的 cache key 是负数(int64_t 的高位为 1),cast 到 uint64_t 后值不同,会导致升级后无法命中已有 cache。

    文件:blockUtil.ccExecOps.cc

    建议:确认 hash 值的 bit pattern 在整个链路中保持一致,添加测试覆盖负 hash 值场景。

  4. streamId() 返回类型变更需确认所有子类同步 [P2]

    GenerateStream::streamId()int64_t 改为 uint64_t。需确认所有继承子类已同步,外部插件如果 override 了 streamId() 会编译失败。

  5. 格式化改动与功能改动混合 [P2]

    大量纯对齐/空格调整与类型变更混在同一 commit 中,增加了 review 难度和 git blame 噪音。建议格式化改动单独一个 commit。

  6. PR description 缺少动机说明 [P3]

    未说明为什么需要改为 uint64_t、兼容性影响评估等。

整体评价

这是一个大范围的类型重构 PR,将 request_idCacheKeyType 从有符号改为无符号。代码改动本身机械且一致,测试也同步更新了。但 proto wire-format 兼容性问题是阻塞级的——int64uint64 在 protobuf 中使用不同的编码方式,直接改类型会导致滚动升级期间 RPC 通信数据错误。reinterpret_cast 桥接也引入了 UB 风险。建议先解决 proto 兼容性问题再合入。

存在阻塞/重要问题,不建议合入

@LLLLKKKK
Copy link
Copy Markdown
Collaborator

🤖 AI Code Review — PR #927

PR 概述

Title: Develop/fix int64
Author: xinfei-shi
规模: 119(GitHub) files, +564/-501

核心目标

request_id 的类型从 int64_t 改为 uint64_t,将 CacheKeyTypeint64_t 改为 uint64_t,并将相关类型定义抽取到独立的 BasicType.h 头文件中。同时将 Types.h 重命名为 CacheTypes.h 以避免命名歧义。


改动逻辑拆解

GitHub 开源仓库变更(主要代码)

1. 类型定义重构(cache/BasicType.h, CacheTypes.h)

  • 新增 BasicType.h,集中定义 CacheKeyType = uint64_tBlockIdxType = int32_tGroupIdType = int32_tLayerIdsType
  • Types.h 重命名为 CacheTypes.h,移除原有的 GroupIdType/LayerIdsType 定义,改为 include BasicType.h
  • KVCacheResource.h 中原有的 CacheKeyType = int64_tBlockIdxType = int32_t 定义被移除,改为 include BasicType.h

2. request_id 类型变更(int64_t -> uint64_t)

  • GenerateInput::request_idGenerateOutputs::request_id 改为 uint64_t
  • GenerateStream::streamId() 返回类型改为 uint64_t
  • EmbeddingInput::request_idEmbeddingStream::streamId() 改为 uint64_t
  • API 层(ChatService、InferenceService、AccessLogWrapper、Exception)全链路跟随变更
  • RPC 层(GenerateContext、PrefillGenerateContext、DecodeRpcServer、LocalRpcServer)全链路跟随变更
  • P2P connector 全链路(ComputedLayerCacheBuffer、P2PBroadcastClient、P2PConnectorScheduler 等)跟随变更

3. CacheKeyType 类型变更(int64_t -> uint64_t)

  • LayerCacheBufferblock_id_map_std::map<int64_t, int> 改为 std::map<CacheKeyType, int>
  • KeyBlockInfo::cache_keyint64_t 改为 CacheKeyType
  • KeyBlockInfoMapstd::unordered_map<int64_t, ...> 改为 std::unordered_map<CacheKeyType, ...>
  • ComputedLayerCacheBufferStore::computed_buffers_unordered_map<int64_t, ...> 改为 unordered_map<uint64_t, ...>

4. Proto 变更

  • model_rpc_service.protorequest_id 字段从 int64 改为 uint64(涉及 GenerateInputPB、GenerateOutputsPB、GenerateRequestPB、BroadcastLoadRequestPB、RemoteFinishRequestPB、RemoteStoreRequestPB、TaskInfoPB、EmbeddingInputPB、EmbeddingHealthRequestPB、P2PConnectorBroadcastTpRequestPB)
  • cache_keys 字段从 repeated int64 改为 repeated uint64
  • CacheStatusPB::cache_keysmap<int64, bool> 改为 map<uint64, bool>
  • tcp_service.protoTcpCacheKeyBlockBufferInfo::keyint64 改为 uint64

5. 日志格式修正

  • 所有 %ld/%d 格式化 request_id/streamId() 的地方改为 %llu + (unsigned long long) cast

6. 兼容性桥接(RemoteConnector)

  • 新增 cacheKeysAsInt64Vec() 函数,通过 reinterpret_cast<const std::vector<int64_t>&>CacheKeysType(现为 vector<uint64_t>)转为 vector<int64_t> 传给 MetaClient

7. 测试更新

  • 所有涉及 request_idcache_key 的测试用例同步更新类型声明

Checklist 检查结果

通用原则

软件工程原则

检查项 结果
SRP ✅ PR 聚焦于类型变更
OCP
LSP
ISP
DIP
DRY ✅ 类型定义集中到 BasicType.h
KISS
YAGNI

架构审视

检查项 结果
抽象边界 ✅ BasicType.h 作为底层类型定义层合理
依赖方向
状态完整性
错误语义
可观测性 ✅ 日志格式已同步更新
可演进性 ❌ Proto 字段类型变更是 breaking change(见问题 1)
可运维性 ❌ 缺少滚动升级兼容方案(见问题 1)

测试

检查项 结果
新功能有对应测试 ✅ 已有测试同步更新
删除的测试有等价替代 N/A
边界 case 覆盖 ❌ 缺少 uint64_t 高位值(>INT64_MAX)的测试(见问题 3)
分布式改动有多卡测试 N/A

代码质量与文档

检查项 结果
无关改动分离 ❌ 混入了大量纯格式化对齐改动(见问题 5)
mega-PR 拆分 ✅ 虽然 119 文件但逻辑单一
Commit 原子性 ✅ 两个 commit 分别处理 request_id 和 cache_key
Commit message 准确性
PR description 说明动机和设计 ❌ PR body 过于简略,未说明为什么需要改为 uint64_t(见问题 6)
日志频率控制

领域检查

A. 兼容性与配置

检查项 结果
1.1 Breaking Change 缺少兼容处理 ❌ Proto int64->uint64 是 wire-format breaking change(见问题 1)
1.2 默认值变更 ✅ InferenceService request_id 默认值从 -1 改为 0,合理
1.12 模型变体配置传播 N/A
1.32 可选依赖/pybind 默认值

B. 正确性与逻辑

检查项 结果
逻辑错误 cacheKeysAsInt64Vec 的 reinterpret_cast 是 UB(见问题 2)
边界 case ❌ hashInt64Vector 返回 int64_t,cast 到 uint64_t 可能改变语义(见问题 3)
1.46 过滤后使用过滤结果
1.55 接口返回类型变更 streamId() 返回类型变更影响所有子类(见问题 4)

C. 线程安全与并发 — 全部 ✅

D. 性能 — 全部 ✅

E. 分布式 — 全部 ✅

F. 跨平台(ROCm/ARM)

检查项 结果
1.50 删除代码后全局搜索遗留引用 ✅ Types.h 重命名后所有 include 已更新
1.51 Proto field number 不复用不重排 ✅ field number 未变,仅类型变更

G. 语言与框架特有 — 全部 ✅

H. 测试与 CI — 全部 ✅

I. 代码质量

检查项 结果
1.4 代码风格统一 ❌ 格式化改动与功能改动混在同一 commit(见问题 5)

Review 意见

问题

  1. Proto wire-format 兼容性:int64 -> uint64 是 breaking change [P0]

    Protobuf 的 int64 使用 varint 编码(ZigZag),而 uint64 使用 plain varint 编码。两者的 wire format 不同:同一个正整数值,int64uint64 编码后的字节序列不同。这意味着:

    • 旧版本客户端(使用 int64 request_id)发送的消息,新版本服务端(使用 uint64 request_id)解析时会得到错误的值
    • 滚动升级期间 prefill/decode 节点版本不一致时,RPC 通信会出现数据错误
    • CacheStatusPB::cache_keysmap<int64, bool> 改为 map<uint64, bool> 同理

    涉及文件:rtp_llm/cpp/model_rpc/proto/model_rpc_service.protortp_llm/cpp/cache/connector/p2p/transfer/tcp/proto/tcp_service.proto

    建议

    • 方案 A:保持 proto 中的 int64 不变,仅在 C++ 层做 static_cast<uint64_t>(pb.request_id())。Proto 是跨进程接口,类型变更需要极其谨慎
    • 方案 B:如果确实需要改 proto,需要新增字段(如 uint64 request_id_v2 = N)并保留旧字段做 fallback,确保滚动升级兼容
  2. cacheKeysAsInt64Vec 的 reinterpret_cast 是未定义行为 [P1]

    inline const std::vector<int64_t>& cacheKeysAsInt64Vec(const CacheKeysType& keys) {
        static_assert(sizeof(CacheKeyType) == sizeof(int64_t));
        return reinterpret_cast<const std::vector<int64_t>&>(keys);
    }

    reinterpret_caststd::vector<uint64_t>std::vector<int64_t> 之间转换违反 strict aliasing rule,是 C++ 标准中的未定义行为。虽然在实践中大多数编译器/平台上能工作,但:

    • 编译器优化(特别是 LTO)可能基于 strict aliasing 假设产生错误代码
    • 这是一个定时炸弹,未来编译器升级可能暴露问题

    文件:rtp_llm/cpp/cache/connector/remote_connector/RemoteConnector.cc

    建议:显式拷贝转换,或者保持 MetaClient 接口侧的 CacheKeysTypeint64_t,在 BasicType.hCacheKeyType 仍用 int64_t(如果 uint64 的需求仅来自 request_id 而非 cache key)。

  3. hash 值从 int64_t cast 到 uint64_t 可能改变 cache 匹配行为 [P1]

    blockUtil.cchashInt64Vector 返回 int64_t,现在被 static_cast<CacheKeyType> 转为 uint64_t。同时 ExecOps.ccrequest_idint64_t tensor 中读取后 cast 为 uint64_t

    如果现有已缓存的 cache key 是负数(int64_t 的高位为 1),cast 到 uint64_t 后值不同。这会导致:

    • 升级后无法命中已有的 cache(cache miss 率突增)
    • 如果 BlockCache 的 LRU key 类型也变了,旧数据无法被正确查找

    文件:rtp_llm/cpp/pybind/common/blockUtil.ccrtp_llm/cpp/core/ExecOps.cc

    建议:确认 hash 值的 bit pattern 在整个链路中是否保持一致。如果 CacheKeyType 改为 uint64_t,但 hash 函数仍返回 int64_t,需要确保所有存储和比较点都使用相同的 cast 方式。建议添加测试覆盖负 hash 值场景。

  4. streamId() 返回类型变更需确认所有子类同步 [P2]

    GenerateStream::streamId()int64_t 改为 uint64_tEmbeddingStream::streamId() 同理。需要确认:

    • 所有继承 GenerateStream 的子类(如 NormalGenerateStream)是否都已同步
    • 外部插件或自定义模型如果 override 了 streamId() 会在编译时报错(返回类型不匹配)

    从 diff 看 NormalGenerateStream 已更新,但建议全局搜索确认无遗漏。

  5. 格式化改动与功能改动混合 [P2]

    大量纯对齐/空格调整(如 P2PConnectorResourceStore.hGenerateStream.h 成员变量对齐、PrefillGenerateContext.h 花括号位置)与类型变更混在同一 commit 中,增加了 review 难度和 git blame 噪音。

    建议:格式化改动单独一个 commit。

  6. PR description 缺少动机说明 [P3]

    PR body 仅写了 "fix cache key type from int64_t -> uint64_t" 和 "fix request id type from int64_t -> uint64_t",但未说明:

    • 为什么需要改为 uint64_t?是否遇到了 request_id 溢出问题?
    • cache key 为什么需要 uint64_t?hash 值是否会超过 INT64_MAX?
    • 这个变更的兼容性影响评估

小问题

  • ExecOps.cc(long)(block_num + reuse_block_num) 的 cast 不够规范,建议用 static_cast<long> 或直接用 %d
  • InferenceService.ccrequest_id 默认值从 -1 改为 0,语义上 0 是否是合法的 request_id?如果 0 表示"未分配",需要确认下游不会把 0 当作有效 ID 处理

整体评价

这是一个大范围的类型重构 PR,将 request_idCacheKeyType 从有符号改为无符号。代码改动本身机械且一致,测试也同步更新了。但 proto wire-format 兼容性问题是阻塞级的——int64uint64 在 protobuf 中使用不同的编码方式,直接改类型会导致滚动升级期间 RPC 通信数据错误。reinterpret_cast 桥接也引入了 UB 风险。建议先解决 proto 兼容性问题再合入。

存在阻塞/重要问题,不建议合入

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants