Files
paddlepaddle--paddle/test/cpp/eager/task_tests/nan_inf_utils_test.cc
T
2026-07-13 12:40:42 +08:00

170 lines
7.2 KiB
C++

// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/fluid/eager/nan_inf_utils.h"
#include <iostream>
#include <limits>
#include <ostream>
#include <string>
#include <tuple>
#include "gtest/gtest.h"
#include "paddle/common/flags.h"
#include "paddle/fluid/framework/tensor_util.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/phi/api/include/api.h"
#include "paddle/phi/api/include/strings_api.h"
#include "paddle/phi/core/kernel_registry.h"
PD_DECLARE_KERNEL(full, CPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(strings_empty, CPU, ALL_LAYOUT);
COMMON_DECLARE_string(check_nan_inf_blacklist);
namespace egr {
using paddle_flags::FLAGS_check_nan_inf_blacklist;
#define CHECK_NAN_INF(tensors) \
{ \
bool caught_exception = false; \
try { \
CheckTensorHasNanOrInf("nan_inf_test", tensors); \
} catch (paddle::platform::EnforceNotMet & error) { \
caught_exception = true; \
std::string ex_msg = error.what(); \
EXPECT_TRUE(ex_msg.find("There are NAN or INF") != std::string::npos); \
} \
EXPECT_TRUE(caught_exception); \
}
#define CHECK_NO_NAN_INF(tensors) \
{ \
bool caught_exception = false; \
try { \
CheckTensorHasNanOrInf("nan_inf_test", tensors); \
} catch (paddle::platform::EnforceNotMet & error) { \
caught_exception = true; \
std::string ex_msg = error.what(); \
EXPECT_TRUE(ex_msg.find("There are NAN or INF") != std::string::npos); \
} \
EXPECT_FALSE(caught_exception); \
}
#define CHECK_APINAME_SKIP(api_name, tensor) \
{ \
bool caught_exception = false; \
try { \
CheckTensorHasNanOrInf(api_name, tensor); \
} catch (paddle::platform::EnforceNotMet & error) { \
caught_exception = true; \
} \
EXPECT_FALSE(caught_exception); \
}
#define CHECK_APINAME_NO_SKIP(api_name, tensor) \
{ \
bool caught_exception = false; \
try { \
CheckTensorHasNanOrInf(api_name, tensor); \
} catch (paddle::platform::EnforceNotMet & error) { \
caught_exception = true; \
} \
EXPECT_TRUE(caught_exception); \
}
TEST(NanInfUtils, BlacklistSkipCheck) {
auto nan_tensor = paddle::experimental::full(
{3, 4}, std::numeric_limits<double>::quiet_NaN(), phi::DataType::FLOAT64);
FLAGS_check_nan_inf_blacklist = "";
CHECK_APINAME_SKIP("empty", nan_tensor);
// Test that "empty_like" always skips regardless of blacklist
FLAGS_check_nan_inf_blacklist = "";
CHECK_APINAME_SKIP("empty_like", nan_tensor);
// Test with empty blacklist (default behavior)
FLAGS_check_nan_inf_blacklist = "";
CHECK_APINAME_NO_SKIP("some_op", nan_tensor);
// Test with single op in blacklist
FLAGS_check_nan_inf_blacklist = "single_op";
CHECK_APINAME_SKIP("single_op", nan_tensor);
CHECK_APINAME_NO_SKIP("other_op", nan_tensor);
// Even when blacklist is set, these should still skip
CHECK_APINAME_SKIP("empty", nan_tensor);
CHECK_APINAME_SKIP("empty_like", nan_tensor);
// blacklist="op1,op2,op3" and op is in blacklist
FLAGS_check_nan_inf_blacklist = "op1,op2,op3";
CHECK_APINAME_SKIP("op1", nan_tensor);
CHECK_APINAME_SKIP("op2", nan_tensor);
CHECK_APINAME_SKIP("op3", nan_tensor);
// not in blacklist, should perform nan_or_inf check
CHECK_APINAME_NO_SKIP("op4", nan_tensor);
FLAGS_check_nan_inf_blacklist = "";
}
TEST(NanInfUtils, Functions) {
// test all methods
auto tensor = paddle::experimental::full(
{3, 4}, std::numeric_limits<double>::quiet_NaN(), phi::DataType::FLOAT64);
CHECK_NAN_INF(tensor);
auto tensor1 = paddle::experimental::full(
{3, 4}, std::numeric_limits<double>::quiet_NaN(), phi::DataType::FLOAT64);
auto two_tensors = std::make_tuple(tensor, tensor1);
CHECK_NAN_INF(two_tensors);
auto tensor2 = paddle::experimental::full(
{3, 4}, std::numeric_limits<double>::quiet_NaN(), phi::DataType::FLOAT64);
auto three_tensors = std::make_tuple(tensor, tensor1, tensor2);
CHECK_NAN_INF(three_tensors);
auto tensor3 = paddle::experimental::full(
{3, 4}, std::numeric_limits<double>::quiet_NaN(), phi::DataType::FLOAT64);
auto four_tensors = std::make_tuple(tensor, tensor1, tensor2, tensor3);
CHECK_NAN_INF(four_tensors);
auto tensor4 = paddle::experimental::full(
{3, 4}, std::numeric_limits<double>::quiet_NaN(), phi::DataType::FLOAT64);
auto five_tensors =
std::make_tuple(tensor, tensor1, tensor2, tensor3, tensor4);
CHECK_NAN_INF(five_tensors);
auto tensor5 = paddle::experimental::full(
{3, 4}, std::numeric_limits<double>::quiet_NaN(), phi::DataType::FLOAT64);
auto six_tensors =
std::make_tuple(tensor, tensor1, tensor2, tensor3, tensor4, tensor5);
CHECK_NAN_INF(six_tensors);
std::vector<paddle::Tensor> tensor_vec;
tensor_vec.emplace_back(tensor);
tensor_vec.emplace_back(tensor1);
CHECK_NAN_INF(tensor_vec);
paddle::small_vector<std::vector<paddle::Tensor>, egr::kSlotSmallVectorSize>
small_vec;
small_vec.emplace_back(tensor_vec);
CHECK_NAN_INF(small_vec);
// test selected_rows
paddle::Tensor tensor_sr;
auto sr = std::make_shared<phi::SelectedRows>();
*sr->mutable_value() =
*(static_cast<const phi::DenseTensor*>(tensor.impl().get()));
tensor_sr.set_impl(sr);
CHECK_NAN_INF(tensor_sr);
// test other tensor
auto tensor_str = paddle::experimental::strings::empty({3, 4});
CHECK_NO_NAN_INF(tensor_str);
}
} // namespace egr