Skip to content

Conversation

wanghuancoder
Copy link
Contributor

@wanghuancoder wanghuancoder commented Mar 21, 2025

PR Category

Execute Infrastructure

PR Types

New features

Description

maximum minimum mean支持0-Size。
修复了OpTest机制,使其支持0-Size的测试。

本PR作为0-Size修改的示例PR,修改历程介绍如下:

  1. 在PaddleAPITest report/0size_tensor中检索paddle.maximum的错误日志,发现大概率是反向Shape推导的问题。但按规矩应该如下全面排查:
2025-03-10 10:16:20.895948 test begin: paddle.maximum(Tensor([0, 1, 2],"float32"), Tensor([1, 3598, 2],"float32"), )

[accuracy error] backward  paddle.maximum(Tensor([0, 1, 2],"float32"), Tensor([1, 3598, 2],"float32"), ) 
 
Not equal to tolerance rtol=0.01, atol=0.01

(shapes (0, 2), (0, 1, 2) mismatch)
 x: array([], shape=(0, 2), dtype=float32)
 y: array([], shape=(0, 1, 2), dtype=float32)
  1. 前向修复:
    a. 在Paddle代码中检索def maximum,发现maximum的核心实现调用的是_C_ops的maximum
    b. 以_C_ops的maximum在paddle/phi/ops/yaml中检索,发现maximum的InferMeta函数使用到两个:ElementwiseInferMeta,ElementwiseRawInferMeta
    c. 在代码中检索ElementwiseInferMeta,ElementwiseRawInferMeta,并检查其dims(shape)的推导是否正确(在maximum中他的推导是正确的因此不用修改)
    d. 如果修改了maximum的InferMeta函数,则必须同时修改maximum的符号推导函数:在paddle/fluid/pir/dialect/operator/interface/infer_symbolic_shape中检索maximum找到对应的函数进行修改(如果有必要修改)。符号推到的知识介绍见:【快乐开源】CINN编译器符号推导扩量 #66444
    e. 在paddle/phi/kernels中检索maximum,找全所有maximum的实现Kernel。一般Kernel肯定会有CPU、GPU、XPU版本,还有些Kernel还有有OneDNN、Sparse、SelectedRows版本。务必找全、改全。
    f. 对于单输出的Kernel修改方式一般为:
if (out && out->numel() == 0) {
  dev_ctx.template Alloc<T>(out);
  return;
}

g. dev_ctx.template Alloc是在给out分配一个显存长度为0的Alloction。因为0-Size Tensor虽然没有显存,但是有place(device)信息。在Paddle中,Allocation用于存储Place和显存块信息。因此需要分配一个空的有Place的Allocation。
h. 直接return的原因为,如果不return,很多Kernel在拉起CUDA Kernel时,会因为numel为0导致Kernel拉起失败而崩溃。
i. 注意,有些Kernel有多个output,如果只有其中一个output numel为0,其余output仍然需要运算。需要阅读Kernel后精确修改,确保Kernel能够正确执行。
j. 对于maximum,修改了paddle/phi/kernels/legacy/cpu/elementwise_kernel.cc和paddle/phi/kernels/legacy/xpu/elementwise_kernel.cc,之所以没有修改GPU Kernel,因为没有找到。这是因为GPU、CPU共用了paddle/phi/kernels/legacy/cpu/elementwise_kernel.cc里的实现。因为maximum和minimum处理逻辑一致,因此同时修改maximum和minimum
k. maximum和minimum没有找到OneDNN、Sparse、SelectedRows相关的Kernel实现,因此不做处理
3. 反向修复:
a. 在paddle/phi/ops/yaml中检索maximum_grad,找到InferMeta函数为GeneralBinaryGradInferMeta
b. 根据报错日志,分析大概率是反向Shape推导的问题。但实际分析未发现GeneralBinaryGradInferMeta的问题。调试后发现,其实是MaximumGradKernel在处理前向需要Broadcast的场景时,反向需要Reduce。而Reduce没有考虑0-Size的问题,具体逻辑在paddle/phi/kernels/gpu/elementwise_grad.h中ReduceWrapper中
c. 不需要修改Reduce相关逻辑,只需要对GradKernel做0-Size的特殊处理即可。对于maximum_grad修改方式如下,其它算子可以参考如下代码结合算子反向梯度的数学含义做修改:

if (dout.numel() == 0) {
  if (dx) {
    if (dx->numel() == 0) {
      dev_ctx.template Alloc<T>(dx);
    } else {
      phi::Full<T, Context>(
          dev_ctx, phi::IntArray(common::vectorize(dx->dims())), 0, dx);
    }
  }
  if (dy) {
    if (dy->numel() == 0) {
      dev_ctx.template Alloc<T>(dy);
    } else {
      phi::Full<T, Context>(
          dev_ctx, phi::IntArray(common::vectorize(dy->dims())), 0, dy);
    }
  }
  return;
}

d. 依照以上原则修改CPU、GPU、XPU Kernel,没有找到OneDNN、Sparse、SelectedRows相关的Kernel实现,因此不做处理

  1. 添加单测
    a. test/legacy_test/test_maximum_op.py是为了验证反向maximum_grad的正确性
    b. test/legacy_test/test_elementwise_max_op.py是为了验证前向的正确性,以及在Paddle多种不同机制下是否都支持0-Size,机制如:动态图、静态图、老静态图、CINN、组合算子等
    c. 单测本地验证中,暴露了一些新的问题,因此修改了test/legacy_test/op_test.py、python/paddle/incubate/autograd/composite_rules.py(通常不会遇到这种问题,可以不用太关注)
    d. 单测本地验证中,暴露了,我们还需要修改组合算子的maximum相关逻辑,因此修改了paddle/fluid/prim/api/composite_backward/composite_backward_api.h和paddle/fluid/primitive/decomp_rule/decomp_vjp/details.h
    e. 单测本地验证中,OpTest基类使用到了mean,进而暴露了mean不支持0-Size的问题,因此增加了对mean 0-Size的修改。可以看到:
    i. mean的前向处理更复杂一些,因此不同算子的数学含义导致,处理方式有所不同,需要我们逐一分析
    ii. mean除了GPU、CPU、XPU,还有OneDNN,因此共同修改
  2. 回归测试PaddleAPITest tester/api_config/0sizetensor_accuracy.txt、tester/api_config/0sizetensor_paddleonly.txt、“api_config_merged*” 中所有maximum和minimum测试配置

总结大致流程是:

  1. 改InferMeta
  2. 改符号推导
  3. 改Kernel
  4. 改反向
  5. 保证所有Kernel都改到(CPU、GPU、XPU、OneDNN、Sparse、SelectedRows)
  6. 加单测,包括反向专门测试单测和op Test
  7. 改组合算子
  8. PaddleAPITest回测

Pcard-67164

Copy link

paddle-bot bot commented Mar 21, 2025

你的PR提交成功,感谢你对开源项目的贡献!
请关注后续CI自动化测试结果,详情请参考Paddle-CI手册
Your PR has been submitted. Thanks for your contribution!
Please wait for the result of CI firstly. See Paddle CI Manual for details.

Copy link
Contributor

@XiaoguangHu01 XiaoguangHu01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wanghuancoder wanghuancoder merged commit 823a97a into PaddlePaddle:develop Mar 26, 2025
40 checks passed
co63oc pushed a commit to co63oc/Paddle that referenced this pull request Mar 27, 2025
YqGe585 pushed a commit to YqGe585/Paddle that referenced this pull request May 7, 2025
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.

3 participants