Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-73535/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# PaddlePaddle__Paddle-73535

This directory converts Paddle PR #73535 into a SWE-Paddle community task candidate.

## Source

| Field | Value |
| --- | --- |
| Repo | `PaddlePaddle/Paddle` |
| PR | [73535](https://github.com/PaddlePaddle/Paddle/pull/73535) |
| PR title | `[Accuracy diff No.112] Fix accuracy diff for paddle.nn.functional.conv1d API` |
| Base commit | `9c1900ce422e3398bfccf95d3d33ba2cfa91faed` |
| Gold commit | `f8e6a83f6cb3725902082e7fbb011d7c1e8f6406` |
| Merged at | `2025-06-24` |
| Task type | `bug_fix` |
| Resource | CPU |
| Scope | Python API (conv1d float16 on CPU) |

## Summary

Fix `paddle.nn.functional.conv1d` to correctly handle float16 weight/bias on CPU by converting them to float32 before computation and casting the result back to float16.

## Why This Is A Good SWE-Paddle Candidate

- It is derived from a merged Paddle bug-fix PR rather than a synthetic issue.
- The target behavior is isolated to the Python API layer (`conv1d`) and does not require C++ kernel changes.
- The failure is deterministic: the base revision fails when `conv1d` receives float16 weight/bias on CPU because CPU does not support float16 conv operations.
- The task has clear regression coverage for existing float32/float64 conv1d behavior.
- The task runs on CPU and does not require distributed execution, external services, or additional datasets.

## Files

- `proposal.md`: candidate proposal for maintainer triage.
- `instruction.md`: self-contained problem statement for the coding agent.
- `solution/code.patch`: gold implementation patch (Python API changes in `conv.py`).
- `tests/test.patch`: tests exposing the target behavior (adds `TestFunctionalConv1D_CPU_FP16`).
- `tests/test.sh`: minimal target test command.
- `environment/README.md`: environment and reproduction notes.

## Verification

```bash
bash tests/test.sh
```

Expected behavior:

| Revision state | Existing behavior (P2P) | conv1d F2P |
| --- | ---: | ---: |
| Base + `tests/test.patch` | PASS | FAIL |
| Base + `tests/test.patch` + `solution/code.patch` | PASS | PASS |
57 changes: 57 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-73535/environment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Environment Notes

## Expected Environment

- Repository: `PaddlePaddle/Paddle`
- Base commit: `9c1900ce422e3398bfccf95d3d33ba2cfa91faed`
- Gold commit: `f8e6a83f6cb3725902082e7fbb011d7c1e8f6406`
- Resource: CPU
- GPU required: no
- Patch type: Python API (no C++ kernel changes)
- Python dependencies: PaddlePaddle (source build or pre-built), NumPy

The verifier should execute against the Paddle source revision represented by the selected patch state. Since the patch only modifies Python code, no recompilation is needed — only the Python files change.

## Build Instructions

1. Check out `PaddlePaddle/Paddle` at the base commit.
2. Apply `tests/test.patch`.
3. Build Paddle from source (CPU-only build is sufficient):
```bash
mkdir build && cd build
cmake .. -DWITH_GPU=OFF -DWITH_TESTING=ON -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
```
4. Install the built Paddle package.

## Run Order

1. Check out `PaddlePaddle/Paddle` at the base commit.
2. Build and install Paddle from source.
3. Apply `tests/test.patch`.
4. Run the P2P tests; existing conv1d behavior should pass.
5. Run the CPU float16 test; the target case should fail before the fix.
6. Apply `solution/code.patch`.
7. Repackage and reinstall the Python files so the modified `conv.py` takes effect:
```bash
cd python
python setup.py bdist_wheel
pip install --force-reinstall dist/paddlepaddle-*.whl
cd ..
```
8. Run `bash tests/test.sh`; all target tests should pass.

## Minimal Test Command

```bash
bash tests/test.sh
```

## Expected Matrix

| Revision state | P2P | conv1d F2P |
| --- | ---: | ---: |
| Base + test patch | PASS | FAIL |
| Base + test patch + solution patch | PASS | PASS |

No GPU, distributed runtime, external service, or additional dataset is required.
43 changes: 43 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-73535/instruction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 修复 `paddle.nn.functional.conv1d` 在 CPU 上对 float16 weight/bias 的支持

## 详细描述

当 `paddle.nn.functional.conv1d(x, weight, bias, ...)` 在 CPU 设备上运行时,如果 `weight` 或 `bias` 的 dtype 为 `float16`,当前实现会直接调用底层 `conv2d` 算子,但 CPU 的 `conv2d` 算子不支持 `float16` 输入,导致运行时报错或精度异常。

典型表现包括:

- CPU 环境下传入 float16 的 weight/bias 时,conv1d 计算报错或产生错误结果
- PaddleAPITest 精度对比测试中 `paddle.nn.functional.conv1d` 在 CPU 上出现 accuracy diff

例如:

```python
import paddle
import paddle.nn.functional as F

with paddle.base.device_guard("cpu"):
x = paddle.ones([1, 1, 1])
w = paddle.ones([1, 1, 1]).astype(paddle.float16)
b = paddle.ones([1]).astype(paddle.float16)
y = F.conv1d(x, w, b)
# 期望: y 的值为 [[[2]]],dtype 为 float16
```

上述调用中 weight 和 bias 均为 float16,在 CPU 上应能正确执行并返回 float16 类型的结果。

当前 `conv1d` 函数在将 1D 卷积转换为 2D 卷积之前,没有对 CPU 设备上的 float16 输入进行类型转换处理。需要在调用底层 conv2d 算子之前,检测 CPU 设备并将 float16 的 weight 和 bias 临时转换为 x 的 dtype(通常为 float32),完成计算后再将结果转换回 float16。

## 验收说明

- 当 CPU 设备上 weight 或 bias 为 float16 时,`paddle.nn.functional.conv1d` 应正常完成计算
- 输出的 dtype 应保持为 float16(与输入 weight 的 dtype 一致)
- 输出的数值应与 GPU 上 float16 conv1d 的结果一致(精度在可接受范围内)
- 非 float16 输入(float32、float64 等)下的 conv1d 行为不得退化
- 非 CPU 设备(GPU)上的 conv1d 行为不受影响

## 技术要求

- 熟悉 Python 和 Paddle 动态图 API 开发
- 了解 Paddle 设备(device)检测和 dtype 转换机制
- 了解 conv1d 到 conv2d 的转换实现
- 不需要修改 C++ kernel,仅需修改 Python 层代码
58 changes: 58 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-73535/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# SWE-Paddle Task Proposal: PaddlePaddle__Paddle-73535

## 1. 来源信息

- Instance ID: `PaddlePaddle__Paddle-73535`
- PR 链接: https://github.com/PaddlePaddle/Paddle/pull/73535
- PR 标题: `[Accuracy diff No.112] Fix accuracy diff for paddle.nn.functional.conv1d API`
- Base commit: `9c1900ce422e3398bfccf95d3d33ba2cfa91faed`
- Gold commit: `f8e6a83f6cb3725902082e7fbb011d7c1e8f6406`
- Merged at: 2025-06-24
- 你的身份: contributor

## 2. 问题一句话

`paddle.nn.functional.conv1d` 在 CPU 上不支持 float16 的 weight/bias,需要在 Python 层将 float16 临时转为 float32 计算后再转回 float16。

## 3. 为什么适合作为 SWE-Paddle 样本

- **真实性**: 来自 PaddleAPITest 精度对比测试发现的真实问题(PFCCLab/PaddleAPITest#306)。
- **代表性**: 覆盖 Python API 层的设备/dtype 兼容性修复,涉及设备检测、dtype 转换和结果还原。
- **边界清楚**: 目标仅限 CPU 设备上 float16 weight/bias 的 conv1d 调用;其他设备和 dtype 不受影响。
- **非平凡性**: 修复需要理解 conv1d 到 conv2d 的转换流程,在正确的位置插入 dtype 转换逻辑,并确保输出 dtype 正确还原。
- **回归护栏明确**: 目标 F2P 可覆盖 CPU float16 conv1d 测试;同文件中已有的 `TestFunctionalConv1DError` 等标准测试用例可作为 P2P 护栏。

## 4. 任务类型和标签

- 任务类型: `bug_fix`
- 执行后端: `cpu`
- 设备范围: `cpu_only`
- 模块标签: `[python_api, conv1d, float16, cpu_compatibility, dtype_conversion]`

## 5. 验证思路

- 目标测试命令: `bash tests/test.sh`
- 目标测试文件:
- `test/legacy_test/test_functional_conv1d.py`(`TestFunctionalConv1D_CPU_FP16`)
- P2P 候选: 同文件中已有的 `TestFunctionalConv1DError`(含 `Case1`、`Case2`)等标准 conv1d 测试用例。
- 修复前预期: `base_commit` + `tests/test.patch` 后,CPU float16 conv1d 测试失败(CPU conv2d 不支持 float16)。
- 修复后预期: 继续应用 `solution/code.patch` 后,CPU float16 conv1d 正常返回正确结果,P2P 存量测试仍然通过。

## 6. 环境与资源

- 是否能提供 Docker: 无
- Dockerfile 或镜像地址: 暂无
- Paddle 来源: `PaddlePaddle/Paddle` source checkout at `base_commit`,需要源码编译(或安装对应版本的 Paddle)。
- OS / Python / CUDA / cuDNN / 其他关键依赖: Linux CPU + Python + numpy;编译需要 CMake、GCC;不要求 CUDA/cuDNN(CPU 编译即可验证)。
- 硬件: CPU 即可(编译和测试均不需要 GPU)。
- patch 类型: 仅 Python 代码修改(`python/paddle/nn/functional/conv.py`),无需重新编译。
- 最小测试命令: `bash tests/test.sh`
- 是否有 oracle 日志: 无

## 7. 风险自查

- 泄露风险: 正式 `instruction.md` 只描述「conv1d 在 CPU 上对 float16 weight/bias 的行为异常」,不指出具体的转换代码位置或实现细节。
- 环境风险: 中。任务需要 Paddle 源码环境,但 patch 仅涉及 Python 文件,无需重新编译。
- flaky 风险: 低。测试使用固定的小 tensor 构造,不依赖随机数差异或多设备同步。
- 拆分风险: 低。该 PR 目标集中在 `conv1d` 函数的 CPU float16 兼容处理,测试明确指向 `TestFunctionalConv1D_CPU_FP16`,适合作为一个独立样本。
- 其他不确定点: 完整任务包阶段应确认新增 F2P(`TestFunctionalConv1D_CPU_FP16`)在 `base_commit` 上确实失败。
46 changes: 46 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-73535/solution/code.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
diff --git a/python/paddle/nn/functional/conv.py b/python/paddle/nn/functional/conv.py
index 5e5cfed220..067de2c6cf 100644
--- a/python/paddle/nn/functional/conv.py
+++ b/python/paddle/nn/functional/conv.py
@@ -16,6 +16,7 @@ from __future__ import annotations

from typing import TYPE_CHECKING

+import paddle
from paddle import _C_ops, _legacy_C_ops, get_flags, in_dynamic_mode, pir
from paddle.base.framework import _global_flags, in_dynamic_or_pir_mode
from paddle.device import (
@@ -458,6 +459,15 @@ def conv1d(
dilation = [1, *convert_to_list(dilation, 1, "dilation")]
from ...tensor.creation import assign as paddle_assign

+ # cpu not support float16, need to convert dtype.
+ float16_convert = False
+ if paddle.device.get_device() == "cpu":
+ if weight.dtype == paddle.float16:
+ float16_convert = True
+ weight = weight.astype(x.dtype)
+ if bias is not None and bias.dtype == paddle.float16:
+ float16_convert = True
+ bias = bias.astype(x.dtype)
weight = paddle_assign(weight)
weight = unsqueeze(weight, axis=[-2])

@@ -475,7 +485,6 @@ def conv1d(

squeeze_axis = -3 if channel_last else -2
x = unsqueeze(x, axis=[squeeze_axis])
-
if in_dynamic_or_pir_mode():
if l_type == 'conv2d':
out = _C_ops.conv2d(
@@ -530,6 +539,9 @@ def conv1d(
if bias is not None:
out = _add_with_axis(out, bias, axis=channel_dim)
out = squeeze(out, axis=[squeeze_axis])
+ if float16_convert:
+ # out is float16
+ out = out.astype(paddle.float16)
return out


36 changes: 36 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-73535/tests/test.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
diff --git a/test/legacy_test/test_functional_conv1d.py b/test/legacy_test/test_functional_conv1d.py
index 751b35b255..760e1a2f2b 100644
--- a/test/legacy_test/test_functional_conv1d.py
+++ b/test/legacy_test/test_functional_conv1d.py
@@ -82,5 +82,31 @@ class TestFunctionalConv1DErrorCase2(TestFunctionalConv1DError):
self.data_format = "NCL"


+class TestFunctionalConv1D_CPU_FP16(TestCase):
+ def setUp(self):
+ self.padding = 0
+ self.stride = 1
+ self.dilation = 1
+ self.groups = 1
+ self.data_format = "NCL"
+
+ def test_cpu_fp16(self):
+ with dg.guard(paddle.CPUPlace()):
+ x = paddle.ones([1, 1, 1])
+ w = paddle.ones([1, 1, 1]).astype(paddle.float16)
+ b = paddle.ones([1]).astype(paddle.float16)
+ y = F.conv1d(
+ x,
+ w,
+ b,
+ padding=self.padding,
+ stride=self.stride,
+ dilation=self.dilation,
+ groups=self.groups,
+ data_format=self.data_format,
+ )
+ np.testing.assert_allclose(y.numpy(), [[[2]]])
+
+
if __name__ == "__main__":
unittest.main()
8 changes: 8 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-73535/tests/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail

# P2P tests (pass-to-pass)
python -m pytest test/legacy_test/test_functional_conv1d.py::TestFunctionalConv1DError -q

# F2P tests (fail-to-pass)
python -m pytest test/legacy_test/test_functional_conv1d.py::TestFunctionalConv1D_CPU_FP16 -q