|
4 | 4 | import contextlib |
5 | 5 | import gc |
6 | 6 | import inspect |
| 7 | +import math |
7 | 8 | import os |
| 9 | +import re |
8 | 10 | from dataclasses import dataclass |
9 | 11 |
|
10 | 12 | import numpy |
@@ -52,6 +54,8 @@ def __getattr__(self, name): |
52 | 54 |
|
53 | 55 | torch = _LazyTorch() |
54 | 56 |
|
| 57 | +_GPU_DEVICE_PATTERN = re.compile(r"^(cuda|gpu):(\d+)$", re.IGNORECASE) |
| 58 | + |
55 | 59 |
|
56 | 60 | CUDA_ERROR = frozenset( |
57 | 61 | [ |
@@ -292,6 +296,75 @@ def classify_runtime_error(error_msg): |
292 | 296 | return None, False |
293 | 297 |
|
294 | 298 |
|
| 299 | +def _contains_non_finite_scalar(value): |
| 300 | + if isinstance(value, bool) or isinstance(value, int): |
| 301 | + return False |
| 302 | + if isinstance(value, float): |
| 303 | + return not math.isfinite(value) |
| 304 | + if isinstance(value, numpy.generic): |
| 305 | + try: |
| 306 | + return not numpy.isfinite(value).item() |
| 307 | + except Exception: |
| 308 | + return False |
| 309 | + if isinstance(value, complex): |
| 310 | + return not math.isfinite(value.real) or not math.isfinite(value.imag) |
| 311 | + if isinstance(value, TensorConfig): |
| 312 | + return False |
| 313 | + if isinstance(value, (list, tuple)): |
| 314 | + return any(_contains_non_finite_scalar(item) for item in value) |
| 315 | + if isinstance(value, (dict, collections.OrderedDict)): |
| 316 | + return any(_contains_non_finite_scalar(item) for item in value.values()) |
| 317 | + return False |
| 318 | + |
| 319 | + |
| 320 | +def _normalize_visible_gpu_device(value): |
| 321 | + if not isinstance(value, str): |
| 322 | + return value |
| 323 | + match = _GPU_DEVICE_PATTERN.match(value) |
| 324 | + if match is None: |
| 325 | + return value |
| 326 | + try: |
| 327 | + gpu_count = paddle.device.cuda.device_count() |
| 328 | + except Exception: |
| 329 | + return value |
| 330 | + if gpu_count <= 0: |
| 331 | + return value |
| 332 | + return f"cuda:{int(match.group(2)) % gpu_count}" |
| 333 | + |
| 334 | + |
| 335 | +def _normalize_runtime_value_tree(value): |
| 336 | + if isinstance(value, TensorConfig): |
| 337 | + return value |
| 338 | + if isinstance(value, list): |
| 339 | + return [_normalize_runtime_value_tree(item) for item in value] |
| 340 | + if isinstance(value, tuple): |
| 341 | + return tuple(_normalize_runtime_value_tree(item) for item in value) |
| 342 | + if isinstance(value, collections.OrderedDict): |
| 343 | + return collections.OrderedDict( |
| 344 | + (key, _normalize_runtime_value_tree(item)) for key, item in value.items() |
| 345 | + ) |
| 346 | + if isinstance(value, dict): |
| 347 | + return {key: _normalize_runtime_value_tree(item) for key, item in value.items()} |
| 348 | + return _normalize_visible_gpu_device(value) |
| 349 | + |
| 350 | + |
| 351 | +def _normalize_shape_like_api_arguments(api_name, args): |
| 352 | + if api_name in {"paddle.zeros", "paddle.ones", "paddle.empty"}: |
| 353 | + if len(args) > 1 and not isinstance(args[0], (list, tuple, TensorConfig)): |
| 354 | + return [list(args)] |
| 355 | + if api_name == "paddle.full": |
| 356 | + if len(args) > 1 and not isinstance(args[0], (list, tuple, TensorConfig)): |
| 357 | + return [list(args[:-1]), args[-1]] |
| 358 | + return list(args) |
| 359 | + |
| 360 | + |
| 361 | +def normalize_api_arguments(api_name, args, kwargs): |
| 362 | + normalized_args = _normalize_shape_like_api_arguments(api_name, args) |
| 363 | + normalized_args = _normalize_runtime_value_tree(normalized_args) |
| 364 | + normalized_kwargs = _normalize_runtime_value_tree(kwargs) |
| 365 | + return normalized_args, normalized_kwargs |
| 366 | + |
| 367 | + |
295 | 368 | def get_arg(api_config, arg_pos, arg_name, default=None): |
296 | 369 | if 0 <= arg_pos < len(api_config.args): |
297 | 370 | return api_config.args[arg_pos] |
@@ -551,6 +624,36 @@ def report_compare_error( |
551 | 624 | raise err |
552 | 625 | return log_type, fatal |
553 | 626 |
|
| 627 | + @contextlib.contextmanager |
| 628 | + def disable_paddle_nan_inf_check_if_needed(self): |
| 629 | + if not _contains_non_finite_scalar( |
| 630 | + self.api_config.args |
| 631 | + ) and not _contains_non_finite_scalar(self.api_config.kwargs): |
| 632 | + yield |
| 633 | + return |
| 634 | + |
| 635 | + flag_name = "FLAGS_check_nan_inf" |
| 636 | + original_flags = None |
| 637 | + try: |
| 638 | + original_flags = paddle.get_flags([flag_name]) |
| 639 | + except Exception: |
| 640 | + original_flags = None |
| 641 | + |
| 642 | + if original_flags and flag_name in original_flags: |
| 643 | + try: |
| 644 | + paddle.set_flags({flag_name: False}) |
| 645 | + except Exception: |
| 646 | + original_flags = None |
| 647 | + |
| 648 | + try: |
| 649 | + yield |
| 650 | + finally: |
| 651 | + if original_flags and flag_name in original_flags: |
| 652 | + try: |
| 653 | + paddle.set_flags({flag_name: original_flags[flag_name]}) |
| 654 | + except Exception: |
| 655 | + pass |
| 656 | + |
554 | 657 | def need_skip(self, paddle_only=False): |
555 | 658 | # not support |
556 | 659 | if "sparse" in self.api_config.api_name: |
@@ -627,12 +730,18 @@ def ana_api_info(self): |
627 | 730 | return self.ana_paddle_api_info() and self.ana_torch_api_info() |
628 | 731 |
|
629 | 732 | def ana_paddle_api_info(self): |
| 733 | + self.api_config.args, self.api_config.kwargs = normalize_api_arguments( |
| 734 | + self.api_config.api_name, self.api_config.args, self.api_config.kwargs |
| 735 | + ) |
630 | 736 | self.paddle_api = eval(self.api_config.api_name) |
631 | 737 | self.paddle_args_config = self.api_config.args |
632 | 738 | self.paddle_kwargs_config = self.api_config.kwargs |
633 | 739 | return True |
634 | 740 |
|
635 | 741 | def ana_torch_api_info(self): |
| 742 | + self.api_config.args, self.api_config.kwargs = normalize_api_arguments( |
| 743 | + self.api_config.api_name, self.api_config.args, self.api_config.kwargs |
| 744 | + ) |
636 | 745 | self.torch_args_config = [] |
637 | 746 | self.torch_kwargs_config = collections.OrderedDict() |
638 | 747 | self.paddle_merged_kwargs_config = collections.OrderedDict() |
|
0 commit comments