Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
321f32b
change for enable_compat
Manfredss Jun 29, 2026
9bf7bfb
add two left api
Manfredss Jun 29, 2026
204c7a1
Merge branch 'master' of https://github.com/paddlepaddle/paconvert in…
Manfredss Jul 3, 2026
edb4042
[API Compatibility] inject enable_compat(level=2) so prefix-converted…
Manfredss Jul 3, 2026
1ff4284
Merge branch 'master' of https://github.com/paddlepaddle/paconvert in…
Manfredss Jul 7, 2026
020ce44
Merge branch 'master' of https://github.com/paddlepaddle/paconvert in…
Manfredss Jul 7, 2026
e584efa
[API Compatibility] refine enable_compat injection; activate compat r…
Manfredss Jul 7, 2026
bfff52a
Merge branch 'patch_compat' of https://github.com/manfredss/paconvert…
Manfredss Jul 7, 2026
3dcd2a1
update ChangePrefixMatcher for those can passed under enable_compat(l…
Manfredss Jul 8, 2026
81a3c07
ChangePrefixMatcher for BatchNorm1d/2d/3d
Manfredss Jul 8, 2026
8170d4f
[API Compatibility] fix softmin/allclose/sort matchers under enable_c…
Manfredss Jul 9, 2026
f04bbf3
fix code conversion mis-alignment
Manfredss Jul 9, 2026
9bef7f9
Merge upstream master into patch_compat
Manfredss Jul 14, 2026
838a8a5
restore test script
Manfredss Jul 14, 2026
f7e1c04
update min-mode consistency baselines
Manfredss Jul 14, 2026
5fe7de1
fix default-mode consistency: dedupe injected imports, update baselines
Manfredss Jul 14, 2026
14d8aeb
Simplify ImportTransformer.visit_Module to insert paddle imports and …
Manfredss Jul 15, 2026
e0808c4
Merge branch 'patch_compat' of https://github.com/manfredss/paconvert…
Manfredss Jul 15, 2026
6bd002d
paddle_package == paddle and add once
Manfredss Jul 16, 2026
f8f344a
Merge branch 'master' of https://github.com/paddlepaddle/paconvert in…
Manfredss Jul 17, 2026
961af0c
update after paddle changed
Manfredss Jul 20, 2026
d8f6e9d
fix
Manfredss Jul 22, 2026
62739d7
Merge branch 'master' of https://github.com/paddlepaddle/paconvert in…
Manfredss Jul 22, 2026
7bb47d1
improve
Manfredss Jul 22, 2026
67be297
AvgPool1/2/3d, BatchNorm1/2/3d, MultiheadAttention, Tensor.split to C…
Manfredss Jul 24, 2026
1f774a4
Merge branch 'master' of https://github.com/paddlepaddle/paconvert in…
Manfredss Jul 27, 2026
9c52c23
fix
Manfredss Jul 28, 2026
e39b042
add fix for split, to help distinguish from string split() and Tensor…
Manfredss Jul 28, 2026
8ee2f99
fix
Manfredss Jul 30, 2026
22d59d6
delete same conversion param for nn.functional.softmin
Manfredss Jul 30, 2026
7f11a54
enhance three Tensor api tests, enhance Categorical tests, and PReLU …
Manfredss Jul 30, 2026
5362b97
still fix split typo
Manfredss Jul 30, 2026
1f99f24
clean
Manfredss Jul 31, 2026
d9a9a74
split root cause
Manfredss Jul 31, 2026
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
206 changes: 39 additions & 167 deletions paconvert/api_mapping.json

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions paconvert/api_matcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,11 @@ def get_paddle_class_nodes(self, func, args, kwargs):
if self.transformer.mode == "min":
self.paddle_api = astor.to_source(func).strip("\n")
else:
self.parse_func(func)
func_str = astor.to_source(func).strip("\n")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

你为啥不直接修正parse_func呢,修问题根源

paddle_api = self.get_paddle_api()
paddle_class = func_str.rsplit(".", 1)[0]
paddle_class_api = paddle_api.rsplit(".", 1)[0]
self.paddle_api = paddle_api.replace(paddle_class_api, paddle_class, 1)

args = self.parse_args(args)
kwargs = self.parse_kwargs(kwargs, allow_none=True)
Expand Down Expand Up @@ -5799,7 +5803,9 @@ def reduce_scatter_tensor(output, input, op, group, async_op):
if input.shape[0] == world_size:
input_list = paddle.unstack(input, axis=0)
else:
input_list = paddle.split(input, num_or_sections=world_size, axis=0)
input_list = paddle.tensor.split(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这个又是有啥bug不修吗

input, num_or_sections=world_size, axis=0
)
paddle.distributed.reduce_scatter(output, input_list, op, group, async_op)
"""
)
Expand Down
3 changes: 1 addition & 2 deletions paconvert/attribute_mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@
"torch.Tensor.is_meta": {},
"torch.Tensor.is_quantized": {},
"torch.Tensor.is_sparse": {
"Matcher": "Attribute2Func",
"paddle_api": "paddle.Tensor.is_sparse"
"Matcher": "ChangePrefixMatcher"
},
"torch.Tensor.is_sparse_csr": {
"Matcher": "Attribute2Func",
Expand Down
25 changes: 20 additions & 5 deletions paconvert/transformer/import_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,6 @@ def visit_Module(self, node):
'import torch_package' has been removed already, add 'import paddle_package'
"""
super(ImportTransformer, self).generic_visit(node)
line_NO = 1
paddle_package_list = []
for torch_package in self.imports_map[self.file]["torch_packages"]:
paddle_package_list.append(
Expand All @@ -515,13 +514,29 @@ def visit_Module(self, node):
for may_torch_package in self.imports_map[self.file]["may_torch_packages"]:
paddle_package_list.append(may_torch_package)

for paddle_package in paddle_package_list:
import_code = ""
enable_compat_code = ""
for paddle_package in dict.fromkeys(paddle_package_list):
import_code += f"import {paddle_package}\n"
if paddle_package == "paddle":
enable_compat_code = "paddle.enable_compat(level=2)\n"

import_code += enable_compat_code

if import_code:
log_info(
self.logger,
f"add 'import {paddle_package}' in line {line_NO}",
f"add '{import_code.strip()}' ",
self.file_name,
)
import_end = 1 if ast.get_docstring(node, clean=False) else 0
while (
import_end < len(node.body)
and isinstance(node.body[import_end], ast.ImportFrom)
and node.body[import_end].module == "__future__"
):
import_end += 1
self.record_scope(
(self.root, "body", 0), ast.parse(f"import {paddle_package}").body
(self.root, "body", import_end), ast.parse(import_code).body
)
line_NO += 1
return node
18 changes: 17 additions & 1 deletion scripts/ci/run_cpu_unittest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ echo '**************************************************************************
echo "Checking code cpu unit test by pytest ..."
set +e

ISOLATED_TESTS=(
tests/test_set_num_interop_threads.py
)

PYTEST_IGNORE=(
--ignore=tests/test_backends_cuda_is_built.py
--ignore=tests/test_cuda_is_bf16_supported.py
Expand All @@ -49,15 +53,27 @@ PYTEST_IGNORE=(
--ignore=tests/test_hub_load.py
--ignore=tests/test_hub_load_state_dict_from_url.py
)
for test_file in "${ISOLATED_TESTS[@]}"; do
PYTEST_IGNORE+=(--ignore="${test_file}")
done

python -m pytest -v -s -p no:warnings "${ISOLATED_TESTS[@]}" \
--reruns=3 2>&1 | tee pytest.log
isolated_errors=${PIPESTATUS[0]}

python -m pytest -v -s -p no:warnings "${PYTEST_IGNORE[@]}" --reruns=3 ./tests 2>&1 | tee pytest.log
python -m pytest -v -s -p no:warnings "${PYTEST_IGNORE[@]}" \
--reruns=3 ./tests 2>&1 | tee -a pytest.log
check_errors=${PIPESTATUS[0]}
if [ ${check_errors} -ne 0 ]; then
echo "Rerun CPU unit test"
python -m pytest -v -s -p no:warnings "${PYTEST_IGNORE[@]}" --lf ./tests 2>&1 | tee -a pytest.log
check_errors=${PIPESTATUS[0]}
fi

if [ ${isolated_errors} -ne 0 ]; then
check_errors=${isolated_errors}
fi

echo '******************************************************************************'
if [ ${check_errors} -ne 0 ]; then
echo "Your PR code CPU unit test check FAILED"
Expand Down
38 changes: 19 additions & 19 deletions scripts/ci/run_gpu_unittest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,40 +39,40 @@ echo '**************************************************************************
echo "Checking code gpu unit test by pytest ..."
set +e

ISOLATED_TESTS=(
tests/test_cuda_stream.py
tests/test_cuda_CUDAGraph.py
tests/test_cuda_set_stream.py
tests/test_set_num_interop_threads.py
)

PYTEST_IGNORE=(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这里分两批跑,第一次跑特定名单,第二次跑其他的

--ignore=tests/test_hub_download_url_to_file.py
--ignore=tests/test_hub_help.py
--ignore=tests/test_hub_list.py
--ignore=tests/test_hub_load.py
--ignore=tests/test_hub_load_state_dict_from_url.py
)
for test_file in "${ISOLATED_TESTS[@]}"; do
PYTEST_IGNORE+=(--ignore="${test_file}")
done

# Run test_cuda_stream.py separately and FIRST (GPU state is clean),
# as it can segfault when run after other GPU tests (Paddle FullKernel issue).
# Running in isolation prevents the segfault from killing the entire test batch.
python -m pytest -v -s -p no:warnings tests/test_cuda_stream.py 2>&1 | tee pytest.log
stream_exit=${PIPESTATUS[0]}
python -m pytest -v -s -p no:warnings "${ISOLATED_TESTS[@]}" \
-n 1 --reruns=3 2>&1 | tee pytest.log
isolated_errors=${PIPESTATUS[0]}

# Run test_cuda_CUDAGraph.py in its own process as well: CUDA graph
# capture/replay leaves Paddle GPU state that can natively crash later
# AMP tests (e.g. test_cuda_amp_GradScaler) in the same pytest worker.
python -m pytest -v -s -p no:warnings tests/test_cuda_CUDAGraph.py 2>&1 | tee -a pytest.log
cudagraph_exit=${PIPESTATUS[0]}

python -m pytest -v -s -p no:warnings "${PYTEST_IGNORE[@]}" --ignore=tests/test_cuda_stream.py --ignore=tests/test_cuda_CUDAGraph.py -n 1 --reruns=3 ./tests 2>&1 | tee -a pytest.log
python -m pytest -v -s -p no:warnings "${PYTEST_IGNORE[@]}" \
-n 1 --reruns=3 ./tests 2>&1 | tee -a pytest.log
check_errors=${PIPESTATUS[0]}
if [ ${check_errors} -ne 0 ]; then
echo "Rerun GPU unit test"
python -m pytest -v -s -p no:warnings "${PYTEST_IGNORE[@]}" --ignore=tests/test_cuda_stream.py --ignore=tests/test_cuda_CUDAGraph.py -n 1 --lf ./tests 2>&1 | tee -a pytest.log
python -m pytest -v -s -p no:warnings "${PYTEST_IGNORE[@]}" \
-n 1 --lf ./tests 2>&1 | tee -a pytest.log
check_errors=${PIPESTATUS[0]}
fi

# Propagate isolated test failures if any
if [ ${stream_exit} -ne 0 ]; then
check_errors=${stream_exit}
fi
if [ ${cudagraph_exit} -ne 0 ]; then
check_errors=${cudagraph_exit}
if [ ${isolated_errors} -ne 0 ]; then
check_errors=${isolated_errors}
fi

echo '******************************************************************************'
Expand Down
72 changes: 44 additions & 28 deletions tests/apibase.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import os
import re
import sys
from contextlib import nullcontext

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

现在为啥还需要搞这些guard?目前已经不影响torch的计算了吧


import numpy as np

Expand All @@ -24,6 +25,13 @@
from paconvert.converter import Converter


def _pytorch_exec_guard():
paddle = sys.modules.get("paddle")
if paddle is None:
return nullcontext()
return paddle.use_compat_guard(enable=False)


class APIBase(object):
def __init__(self, pytorch_api) -> None:
"""
Expand Down Expand Up @@ -87,51 +95,59 @@ def run(
elif compared_tensor_names:
pytorch_ns = {}
try:
exec(pytorch_code, pytorch_ns)
with _pytorch_exec_guard():
exec(pytorch_code, pytorch_ns)
except Exception as e:
raise RuntimeError(f"Failed to execute pytorch code:\n{e}")
pytorch_result = [pytorch_ns[name] for name in compared_tensor_names]
pytorch_ns.clear()

paddle_ns = {}
try:
exec(paddle_code, paddle_ns)
except Exception as e:
raise RuntimeError(f"Failed to execute paddle code:\n{e}")
paddle_result = [paddle_ns[name] for name in compared_tensor_names]
paddle_ns.clear()
import paddle

for i in range(len(compared_tensor_names)):
paddle_ns = {}
with paddle.use_compat_guard(enable=False):
try:
self.compare(
self.pytorch_api,
pytorch_result[i],
paddle_result[i],
check_value,
check_shape,
check_dtype,
check_stop_gradient,
rtol,
atol,
)
exec(paddle_code, paddle_ns)
except Exception as e:
raise AssertionError(f"Unable to align results: {e}")
raise RuntimeError(f"Failed to execute paddle code:\n{e}")
paddle_result = [paddle_ns[name] for name in compared_tensor_names]
paddle_ns.clear()

for i in range(len(compared_tensor_names)):
try:
self.compare(
self.pytorch_api,
pytorch_result[i],
paddle_result[i],
check_value,
check_shape,
check_dtype,
check_stop_gradient,
rtol,
atol,
)
except Exception as e:
raise AssertionError(f"Unable to align results: {e}")
else:
pytorch_ns = {}
try:
exec(pytorch_code, pytorch_ns)
with _pytorch_exec_guard():
exec(pytorch_code, pytorch_ns)
except Exception as e:
raise RuntimeError(f"Failed to execute pytorch code:\n{e}")
finally:
pytorch_ns.clear()

import paddle

paddle_ns = {}
try:
exec(paddle_code, paddle_ns)
except Exception as e:
raise RuntimeError(f"Failed to execute paddle code:\n{e}")
finally:
paddle_ns.clear()
with paddle.use_compat_guard(enable=False):
try:
exec(paddle_code, paddle_ns)
except Exception as e:
raise RuntimeError(f"Failed to execute paddle code:\n{e}")
finally:
paddle_ns.clear()

def compare(
self,
Expand Down
Loading
Loading