[Operator Mechanism] Fix big tensor int64 to int32 narrowing bugs - #79246
Conversation
agent check step 2
CI报告基于以下代码生成(30分钟更新一次): 1 Required任务 : 43/48 通过
2 失败详情🔴 Fleet Unit test (single card) — PR问题(置信度: 中)分析器: 通用分析(fallback) 失败用例:
关键日志:
修复建议:
关联变更: 🔴 Check approval — 需要 Approval(置信度: 高)该 Job 需要人工 Approval,完成审批后 CI 才会继续执行。
|
| PADDLE_ENFORCE_GPU_SUCCESS(cudaDeviceSynchronize()); | ||
| } | ||
| if (FLAGS_alloc_fill_value >= 0) { | ||
| PADDLE_ENFORCE_LE_INT_MAX(FLAGS_alloc_fill_value, "memset fill value"); |
There was a problem hiding this comment.
这个可以约束FLAGS_alloc_fill_value的取值范围是0~255
| if constexpr (dispatch == GradDispatchTag::MulInputGrad) { | ||
| COMPUTE_OFFSET_SINGLE_OUTPUT(replace_index, 1, tid, 2) | ||
| atomicMax(aux_buffer + replace_index, tid); | ||
| atomicMax(aux_buffer + replace_index, static_cast<int>(tid)); |
There was a problem hiding this comment.
在gpu侧无法使用PADDLE_ENFORCE_LE_INT_MAX,已经在对应的host侧添加了对应的PADDLE_ENFORCE_LE_INT_MAX限制
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #79246 +/- ##
==========================================
Coverage ? 97.50%
==========================================
Files ? 6
Lines ? 40
Branches ? 0
==========================================
Hits ? 39
Misses ? 1
Partials ? 0 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| uint32_t main_offset = (numel / (read_lens * threads)) * read_lens * threads; | ||
| uint32_t tail_tid = numel % (read_lens * threads); | ||
| const int64_t block_len = static_cast<int64_t>(read_lens) * threads; | ||
| const int64_t main_offset_64 = (numel_64 / block_len) * block_len; |
There was a problem hiding this comment.
block_len(read_lens)有没有取0的可能性?全链路检查一下
There was a problem hiding this comment.
已进行全链路检查,paddle/phi/kernels/funcs/broadcast_function.h:839 已经在outs[0]->numel() == 0 时直接 return,因此不会继续进入 LaunchBroadcastKernel。
| constexpr int _block = 512; | ||
| int64_t grid = (self_size + _block - 1) / _block; | ||
| const uint32_t grid = GetCudaLaunchGrid( | ||
| self_size, _block, "CastDivKernel CUDA launch grid size"); |
There was a problem hiding this comment.
我理解这里的操作是一个对输入空间的一个收窄,之前的超uint32的grid是否就完全无法支持了?
There was a problem hiding this comment.
CUDA 中 dim3 的 x/y/z 成员类型是 unsigned int。因此超过 uint32_t 范围的 grid 本身就无法被正确表达和支持。旧代码虽然用 int64_t grid 计算,但传入 kernel launch 时仍会隐式转换到 dim3,存在截断/非法 launch 风险;本次修改只是将这种隐式风险改为通过 PADDLE_ENFORCE 显式报错,并不是收窄了原本可正确支持的输入空间。
| int64_t ndim = index_dims.size(); | ||
| int64_t n = inner_dim_size * select_dim_size * outer_dim_size; | ||
| int64_t grid = (n + block - 1) / block; | ||
| const uint32_t grid = GetCudaLaunchGrid( |
There was a problem hiding this comment.
CUDA 中 dim3 的 x/y/z 成员类型是 unsigned int。因此超过 uint32_t 范围的 grid 本身就无法被正确表达和支持。旧代码虽然用 int64_t grid 计算,但传入 kernel launch 时仍会隐式转换到 dim3,存在截断/非法 launch 风险;本次修改只是将这种隐式风险改为通过 PADDLE_ENFORCE 显式报错,并不是收窄了原本可正确支持的输入空间。
| const int threads = 256; | ||
| int64_t x_numel = x->numel(); | ||
| int64_t fsize = H * W * D; | ||
| PADDLE_ENFORCE_LE_INT_MAX(fsize, "sync_batch_norm grad feature size"); |
There was a problem hiding this comment.
假设过强了吧?HWD不是很容易超过uint32吗?是否这种大shape之后就不支持了?
There was a problem hiding this comment.
进一步审查发现,在完成enforce检查后,在代码中还会调用int32与int64两种数据类型。因此已将int32调用处的相关函数参数类型提升至int64
| auto dims = weight.dims(); | ||
| const int rank = dims.size(); | ||
| std::vector<int> real_dims; | ||
| std::vector<int64_t> real_dims; |
There was a problem hiding this comment.
这里real dims里面push了autotype的普通dims,安全吗
There was a problem hiding this comment.
dims 的类型是 phi::DDim,dims[dim] 返回的是维度值,类型是 int64_t 。此处修复了原本的int64到int32的截断问题
| const int64_t axis_dim) { | ||
| int64_t batch_size = prob->dims()[0]; | ||
| int64_t class_num = prob->dims()[1]; | ||
| PADDLE_ENFORCE_EQ( |
There was a problem hiding this comment.
这里是新加的约束条件?我理解这是对输入的约束增强,是必须加入的吗?请解释一下。如果两变量一定相等的话,就说明语义存在冗余,变量数应该进行缩减
There was a problem hiding this comment.
在Infermeta处会对于不想等的情况进行拦截,因此此处的判定并不是必须的正确性问题判定,已删除
PaddlePaddle-bot
left a comment
There was a problem hiding this comment.
🤖 Paddle-CI-Agent | pr_review |
2026-06-12 16:10:37
📋 Review 摘要
PR 概述:修复多处 Paddle C++/CUDA kernel 中 64 位计数向 32 位参数传递前的截断风险。
变更范围:paddle/fluid/pybind/、paddle/phi/backends/、paddle/phi/core/、paddle/phi/kernels/
影响面 Tag:[Operator Mechanism] [Custom Device] [Performance Optimization]
问题
| 级别 | 文件 | 概述 |
|---|---|---|
| 🟡 建议 | PR 级别 | 本 PR 变更量较大(124 文件 / 4249 行),建议按模块拆分以降低审查和回归风险。 |
本轮达到时间上限,未形成新的可阻塞发现;未覆盖部分待后续深挖。
历史 Findings 修复情况
| Finding | 问题 | 状态 |
|---|---|---|
| F1 | sync_batch_norm_kernel.cu 中 fsize 仍基于已收窄到 int 的 H/W/D |
📝 PR 规范检查
PR 标题格式合规([Operator Mechanism]),四个必填 section(PR Category / PR Types / Description / 是否引起精度变化)均已填写,符合模板结构要求。
总体评价
建议拆分方案:
- PR 1: 公共边界检查与基础设施 —
paddle/common/enforce.h、paddle/phi/backends/gpu/gpu_launch_config.h、paddle/phi/core/memory/allocation/allocator.h - PR 2: BLAS/cuDNN/OneDNN 参数边界 —
paddle/phi/kernels/funcs/blas/*、paddle/phi/kernels/funcs/cudnn_rnn_cache.h、paddle/phi/kernels/gpudnn/* - PR 3: 通用 funcs 与 CPU kernel 计数修复 —
paddle/phi/kernels/funcs/*、paddle/phi/kernels/cpu/* - PR 4: GPU/fusion kernel launch 与索引修复 —
paddle/phi/kernels/gpu/*、paddle/phi/kernels/fusion/gpu/* - PR 5: pybind 与 impl 层窄化修复 —
paddle/fluid/pybind/*、paddle/phi/kernels/impl/*
本轮按风险优先审查了公共宏可用性、GPU launch 维度、sync_batch_norm 历史问题、broadcast/conv/cuDNN RNN/BLASLt 等关键语义变更点,未全量覆盖其余机械迁移文件。
|
LGTM,合入后建议等一段时间CICE反馈 |
|
你的PR提交成功,感谢你对开源项目的贡献! |
Backport the SplitFunctor<CPUContext> int->int64_t narrowing fix from PaddlePaddle#79246 so unbind/split on CPU no longer overflows when a per-output column count exceeds INT_MAX (e.g. unbind([2, 2^31], axis=0) via the non-strided path). Pairs with PaddlePaddle#79737 which removed the numel<=INT_MAX guard.
PR Category
Operator Mechanism
PR Types
Bug fixes
Description
本 PR 修复了在扫描 Paddle 源码时发现的多类
int64_t/size_t/long/uint64_t到int/int32_t/uint32_t的真实截断风险,重点解决大张量场景下可能出现的int64 -> int32溢出、截断,以及int乘法在提升到int64_t前已经溢出的问题。扫描和处理目录
本次主要扫描并处理了以下 Paddle 源码目录:
paddle/commonpaddle/fluid/pybindpaddle/phi/backendspaddle/phi/corepaddle/phi/kernels/cpupaddle/phi/kernels/funcspaddle/phi/kernels/fusion/gpupaddle/phi/kernels/gpupaddle/phi/kernels/gpudnnpaddle/phi/kernels/implpaddle/phi/kernels/primitive公共检查能力
本 PR 在
paddle/common/enforce.h中新增了PADDLE_ENFORCE_LE_UINT32_MAX,用于处理uint64_t/size_t/int64_t等宽类型进入uint32_t边界前的上界检查,典型场景包括 CUDAdim3/ kernel launch 维度。PADDLE_ENFORCE_LE_INT_MAX用于int/int32_t边界PADDLE_ENFORCE_LE_UINT32_MAX用于uint32_t边界本 PR 主要处理了以下 case:
CUDA launch 维度截断
grid/block/dim3等 launch dimension 中由 tensor size、shape product、numel 等计算得到的值PADDLE_ENFORCE_LE_UINT32_MAX做上界检查uint32_t下游 int API 边界
int参数的边界PADDLE_ENFORCE_LE_INT_MAX做上界检查static_cast<int>显式转换tensor size 相关截断
numel、stride、offset、shape product 等来源的窄化转换int的内部计算,尽量保持为int64_t写入 INT32 tensor / int 参数结构
size_t/int64_t写入int*buffer、INT32 tensor 或 int 参数结构前的截断风险int 乘法溢出
int/int32_t相乘后再赋值给int64_t的场景int64_t本 PR 跳过了以下不属于真实大张量截断风险或语义边界不清晰的 case:
total_numel < INT_MAX保护的 offset 或 shard lengthHOSTDEVICE路径中不适合直接加入普通 runtime enforce 的位置是否引起精度变化
否