已合并
expf sqrtf接口支持subnormal #4722
xuyiyang创建于 7月29日
expf sqrtf接口支持subnormal #4722
已合并
共 4 个文件变更+295-27
| @@ -29,6 +29,8 @@ | |||
| 29 | #if (__NPU_ARCH__ == 3510) || (__NPU_ARCH__ == 5102) | 29 | #if (__NPU_ARCH__ == 3510) || (__NPU_ARCH__ == 5102) |
| 30 | 30 | ||
| 31 | #define ASCRT_FOUR_BYTE_LEN_U 32U | 31 | #define ASCRT_FOUR_BYTE_LEN_U 32U |
| 32 | +constexpr float __internal_subnormal_boundary = | ||
| 33 | + 1.17549435e-38f; // 1.17549435e-38f: subnormal floating-point number boundary | ||
| 32 | 34 | ||
| 33 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline long int lroundf(float x) | 35 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline long int lroundf(float x) |
| 34 | { | 36 | { |
| @@ -75,7 +77,103 @@ __SIMT_DEVICE_FUNCTIONS_DECL__ inline float fabsf(float x) { return __fabsf(x); | |||
| 75 | 77 | ||
| 76 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline float fmaf(float x, float y, float z) { return __fma(x, y, z); } | 78 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline float fmaf(float x, float y, float z) { return __fma(x, y, z); } |
| 77 | 79 | ||
| 78 | -__SIMT_DEVICE_FUNCTIONS_DECL__ inline float expf(float x) { return __expf(x); } | 80 | +/* |
| 81 | + * Computes a refined sqrt approximation for float inputs. | ||
| 82 | + * | ||
| 83 | + * calculation to move subnormal or very small values into a more stable | ||
| 84 | + * range. The result is scaled back by 2^-12 because sqrt(x * 2^24) | ||
| 85 | + * equals sqrt(x) * 2^12. | ||
| 86 | + * | ||
| 87 | + * then applies one Newton-style correction to inv: | ||
| 88 | + * err0 = 1 - b * inv * inv | ||
| 89 | + * inv = inv + err0 * inv * 0.5 | ||
| 90 | + * | ||
| 91 | + * The final sqrt value is reconstructed and corrected: | ||
| 92 | + * y = inv * b | ||
| 93 | + * err1 = b - y * y | ||
| 94 | + * y = y + 0.5 * inv * err1 | ||
| 95 | + * | ||
| 96 | + * @param x The input value. | ||
| 97 | + * @return The refined square root approximation. | ||
| 98 | + */ | ||
| 99 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float __internal_sqrtf_precise_impl(float x) | ||
| 100 | +{ | ||
| 101 | + constexpr float scale_up = 16777216.0f; // 2^24 | ||
| 102 | + constexpr float scale_down = 0.000244140625f; // 2^-12 | ||
| 103 | + constexpr float half = 0.5f; | ||
| 104 | + | ||
| 105 | + // Return early for zero and positive infinity. | ||
L | |||
| 106 | + if (x == 0.0f || x == ASCRT_INF_F) { | ||
| 107 | + return x; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + // Scale inputs smaller than 1 to the normal range. | ||
| 111 | + bool scaled = x < 1.0f; | ||
| 112 | + float b = scaled ? x * scale_up : x; | ||
| 113 | + | ||
| 114 | + // Compute an approximate reciprocal square root. | ||
| 115 | + float sqrt_b = __sqrtf(b); | ||
| 116 | + float inv = 1.0f / sqrt_b; | ||
| 117 | + | ||
| 118 | + // Refine the reciprocal square root. | ||
| 119 | + float err0 = fmaf(-(b * inv), inv, 1.0f); | ||
| 120 | + inv = fmaf(err0, inv * half, inv); | ||
| 121 | + | ||
| 122 | + // Convert to a square-root approximation, then compensate the sqrt residual. | ||
| 123 | + float y = inv * b; | ||
| 124 | + float err1 = fmaf(-y, y, b); | ||
| 125 | + y = fmaf(inv * half, err1, y); | ||
| 126 | + | ||
| 127 | + // Scale the result back if the input was multiplied by 2^24. | ||
| 128 | + return scaled ? y * scale_down : y; | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +#ifdef __ASC_FTZ__ | ||
| 132 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float __internal_expf(float x) { return __expf(x); } | ||
| 133 | + | ||
| 134 | +#ifdef __ASC_PREC_SQRT__ | ||
| 135 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float __internal_sqrtf(float x) | ||
| 136 | +{ | ||
| 137 | + // Treat positive subnormal inputs as 0 before entering the precise sqrt path. | ||
| 138 | + if (x > 0.0f && x < __internal_subnormal_boundary) { | ||
| 139 | + x = 0.0f; | ||
| 140 | + } | ||
| 141 | + return __internal_sqrtf_precise_impl(x); | ||
| 142 | +} | ||
| 143 | +#else | ||
| 144 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float __internal_sqrtf(float x) { return __sqrtf(x); } | ||
| 145 | +#endif | ||
| 146 | +#endif | ||
| 147 | + | ||
| 148 | +#ifndef __ASC_FTZ__ | ||
| 149 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float __internal_expf(float x) | ||
| 150 | +{ | ||
| 151 | + constexpr float __internal_subnormal_input_boundary = | ||
| 152 | + -87.3365478515625f; // Input range where expf returns a subnormal result | ||
| 153 | + if (x <= __internal_subnormal_input_boundary) { | ||
| 154 | + float half_y = __expf(x * 0.5f); | ||
| 155 | + return half_y * half_y; | ||
| 156 | + } | ||
| 157 | + return __expf(x); | ||
| 158 | +} | ||
| 159 | + | ||
| 160 | +#ifdef __ASC_PREC_SQRT__ | ||
| 161 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float __internal_sqrtf(float x) { return __internal_sqrtf_precise_impl(x); } | ||
| 162 | +#else | ||
| 163 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float __internal_sqrtf(float x) | ||
| 164 | +{ | ||
| 165 | + constexpr float scale_up = 16777216.0f; // 2^24 | ||
| 166 | + constexpr float scale_down = 0.000244140625f; // 2^-12 | ||
| 167 | + // Scale positive subnormal inputs to the normal range, then scale the result back. | ||
| 168 | + if (x < __internal_subnormal_boundary) { | ||
| 169 | + return __sqrtf(x * scale_up) * scale_down; | ||
| 170 | + } | ||
| 171 | + return __sqrtf(x); | ||
| 172 | +} | ||
| 173 | +#endif | ||
| 174 | +#endif | ||
| 175 | + | ||
| 176 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float expf(float x) { return __internal_expf(x); } | ||
| 79 | 177 | ||
| 80 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline float logf(float x) | 178 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline float logf(float x) |
| 81 | { | 179 | { |
| @@ -87,7 +185,7 @@ __SIMT_DEVICE_FUNCTIONS_DECL__ inline float logf(float x) | |||
| 87 | 185 | ||
| 88 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline float log2f(float x) { return logf(x) / logf(2.0f); } | 186 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline float log2f(float x) { return logf(x) / logf(2.0f); } |
| 89 | 187 | ||
| 90 | -__SIMT_DEVICE_FUNCTIONS_DECL__ inline float sqrtf(float x) { return __sqrtf(x); } | 188 | +__SIMT_DEVICE_FUNCTIONS_DECL__ inline float sqrtf(float x) { return __internal_sqrtf(x); } |
| 91 | 189 | ||
| 92 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline float rsqrtf(float x) { return 1.0f / sqrtf(x); } | 190 | __SIMT_DEVICE_FUNCTIONS_DECL__ inline float rsqrtf(float x) { return 1.0f / sqrtf(x); } |
| 93 | 191 | ||
| @@ -28,6 +28,13 @@ set(ASCENDC_TEST_HEADER_FILES | |||
| 28 | ${ASCENDC_DIR}/impl/simt_api | 28 | ${ASCENDC_DIR}/impl/simt_api |
| 29 | ) | 29 | ) |
| 30 | 30 | ||
| 31 | +file(GLOB ASCENDC_TEST_SIMT_COMMON_SRC_FILES | ||
| 32 | + common_simt/*.cpp | ||
| 33 | +) | ||
| 34 | +set(ASCENDC_TEST_ascend950pr_9599_SIMT_SUBNORMAL_CASE_SRC_FILE | ||
| 35 | + ${CMAKE_CURRENT_SOURCE_DIR}/ascendc_case_ascend950pr_9599_simt/test_operator_simt_subnormal.cpp | ||
| 36 | +) | ||
| 37 | + | ||
| 31 | # # ================ simt_api kernel ut ================ | 38 | # # ================ simt_api kernel ut ================ |
| 32 | # ascend950pr_9599 simt test cases | 39 | # ascend950pr_9599 simt test cases |
| 33 | file(GLOB ASCENDC_TEST_ascend950pr_9599_SIMT_CASE_SRC_FILES | 40 | file(GLOB ASCENDC_TEST_ascend950pr_9599_SIMT_CASE_SRC_FILES |
| @@ -41,43 +48,47 @@ file(GLOB ASCENDC_TEST_mc62cm12aa_SIMT_CASE_SRC_FILES | |||
| 41 | ascendc_case_mc62cm12aa_simt/*.cpp | 48 | ascendc_case_mc62cm12aa_simt/*.cpp |
| 42 | ) | 49 | ) |
| 43 | 50 | ||
| 51 | +add_library(simt_api_test_common INTERFACE) | ||
| 52 | +target_compile_definitions(simt_api_test_common INTERFACE | ||
| 53 | + UT_TEST | ||
| 54 | + ASCENDC_OOM=1 | ||
| 55 | + ASCENDC_DUMP=0 | ||
| 56 | + __CCE_KT_TEST__=1 | ||
| 57 | + ASCENDC_CPU_DEBUG=1 | ||
| 58 | + ASCENDC_DEBUG=1 | ||
| 59 | +) | ||
| 60 | +target_include_directories(simt_api_test_common INTERFACE | ||
| 61 | + ${ASCENDC_TEST_HEADER_FILES} | ||
| 62 | + ${ASCEND_CANN_PACKAGE_PATH}/tools/tikicpulib/lib/include | ||
| 63 | + ${ASCEND_CANN_PACKAGE_PATH}/include/base/ | ||
| 64 | + ${ASCEND_CANN_PACKAGE_PATH}/include/metadef/ | ||
| 65 | +) | ||
| 66 | +target_compile_options(simt_api_test_common INTERFACE | ||
| 67 | + -fno-access-control | ||
| 68 | +) | ||
| 69 | +target_link_libraries(simt_api_test_common INTERFACE | ||
| 70 | + $<BUILD_INTERFACE:intf_llt_pub_basic> | ||
| 71 | + kernel_tiling | ||
| 72 | + -Wl,--no-as-needed | ||
| 73 | + error_manager | ||
| 74 | + mmpa | ||
| 75 | + c_sec | ||
| 76 | + -Wl,--as-needed | ||
| 77 | +) | ||
| 78 | + | ||
| 44 | foreach(product_type ${SIMT_PRODUCT_TYPE_LIST}) | 79 | foreach(product_type ${SIMT_PRODUCT_TYPE_LIST}) |
| 45 | add_executable(ascendc_ut_simt_api_${product_type} | 80 | add_executable(ascendc_ut_simt_api_${product_type} |
| 46 | ${ASCENDC_DIR}/tests/main.cpp | 81 | ${ASCENDC_DIR}/tests/main.cpp |
| 47 | - ../common/k3_pvwrap.cpp | ||
| 48 | ${ASCENDC_TEST_${product_type}_SIMT_CASE_SRC_FILES} | 82 | ${ASCENDC_TEST_${product_type}_SIMT_CASE_SRC_FILES} |
| 49 | ) | 83 | ) |
| 50 | 84 | ||
| 51 | target_compile_definitions(ascendc_ut_simt_api_${product_type} PRIVATE | 85 | target_compile_definitions(ascendc_ut_simt_api_${product_type} PRIVATE |
| 52 | - UT_TEST | ||
| 53 | - ASCENDC_OOM=1 | ||
| 54 | - ASCENDC_DUMP=0 | ||
| 55 | - __CCE_KT_TEST__=1 | ||
| 56 | - ASCENDC_CPU_DEBUG=1 | ||
| 57 | - ASCENDC_DEBUG=1 | ||
| 58 | $<$<STREQUAL:${product_type},ascend950pr_9599>:__NPU_ARCH__=3510;__DAV_C310__;__DAV_C310_VEC__> | 86 | $<$<STREQUAL:${product_type},ascend950pr_9599>:__NPU_ARCH__=3510;__DAV_C310__;__DAV_C310_VEC__> |
| 59 | $<$<STREQUAL:${product_type},mc62cm12aa>:__NPU_ARCH__=5102> | 87 | $<$<STREQUAL:${product_type},mc62cm12aa>:__NPU_ARCH__=5102> |
| 60 | ) | 88 | ) |
| 61 | 89 | ||
| 62 | - target_include_directories(ascendc_ut_simt_api_${product_type} PRIVATE | ||
| 63 | - ${ASCENDC_TEST_HEADER_FILES} | ||
| 64 | - ${ASCEND_CANN_PACKAGE_PATH}/tools/tikicpulib/lib/include | ||
| 65 | - ${ASCEND_CANN_PACKAGE_PATH}/include/base/ | ||
| 66 | - ${ASCEND_CANN_PACKAGE_PATH}/include/metadef/ | ||
| 67 | - ) | ||
| 68 | - | ||
| 69 | - target_compile_options(ascendc_ut_simt_api_${product_type} PRIVATE | ||
| 70 | - -fno-access-control | ||
| 71 | - ) | ||
| 72 | - | ||
| 73 | target_link_libraries(ascendc_ut_simt_api_${product_type} PRIVATE | 90 | target_link_libraries(ascendc_ut_simt_api_${product_type} PRIVATE |
| 74 | - $<BUILD_INTERFACE:intf_llt_pub_basic> | 91 | + simt_api_test_common |
| 75 | - kernel_tiling | ||
| 76 | - -Wl,--no-as-needed | ||
| 77 | - error_manager | ||
| 78 | - mmpa | ||
| 79 | - c_sec | ||
| 80 | - -Wl,--as-needed | ||
| 81 | ) | 92 | ) |
| 82 | 93 | ||
| 83 | run_llt_test( | 94 | run_llt_test( |
| @@ -92,4 +103,40 @@ foreach(product_type ${SIMT_PRODUCT_TYPE_LIST}) | |||
| 92 | add_dependencies(ascendc_ut_simt_api_${product_type} math_bfloat16) | 103 | add_dependencies(ascendc_ut_simt_api_${product_type} math_bfloat16) |
| 93 | add_subdirectory(math_cpp) | 104 | add_subdirectory(math_cpp) |
| 94 | add_dependencies(ascendc_ut_simt_api_${product_type} math_cpp) | 105 | add_dependencies(ascendc_ut_simt_api_${product_type} math_cpp) |
| 106 | + | ||
| 107 | + if("${product_type}" STREQUAL "ascend950pr_9599") | ||
| 108 | + set(SIMT_SUBNORMAL_TARGETS | ||
| 109 | + ascendc_ut_simt_subnormal_ftz_false_prec_false | ||
| 110 | + ascendc_ut_simt_subnormal_ftz_false_prec_true | ||
| 111 | + ascendc_ut_simt_subnormal_ftz_true_prec_false | ||
| 112 | + ascendc_ut_simt_subnormal_ftz_true_prec_true | ||
| 113 | + ) | ||
| 114 | + | ||
| 115 | + foreach(target_name ${SIMT_SUBNORMAL_TARGETS}) | ||
| 116 | + add_executable(${target_name} | ||
| 117 | + ${ASCENDC_DIR}/tests/main.cpp | ||
| 118 | + ${ASCENDC_TEST_SIMT_COMMON_SRC_FILES} | ||
| 119 | + ${ASCENDC_TEST_ascend950pr_9599_SIMT_SUBNORMAL_CASE_SRC_FILE} | ||
| 120 | + ) | ||
| 121 | + | ||
| 122 | + target_link_libraries(${target_name} PRIVATE simt_api_test_common) | ||
| 123 | + target_compile_definitions(${target_name} PRIVATE | ||
| 124 | + __NPU_ARCH__=3510 | ||
| 125 | + __DAV_C310__ | ||
| 126 | + __DAV_C310_VEC__ | ||
| 127 | + ) | ||
| 128 | + | ||
| 129 | + if("${target_name}" MATCHES "_ftz_true_") | ||
| 130 | + target_compile_definitions(${target_name} PRIVATE __ASC_FTZ__) | ||
| 131 | + endif() | ||
| 132 | + if("${target_name}" MATCHES "_prec_true$") | ||
| 133 | + target_compile_definitions(${target_name} PRIVATE __ASC_PREC_SQRT__) | ||
| 134 | + endif() | ||
| 135 | + | ||
| 136 | + run_llt_test( | ||
| 137 | + TARGET ${target_name} | ||
| 138 | + TASK_NUM 1 | ||
| 139 | + ) | ||
| 140 | + endforeach() | ||
| 141 | + endif() | ||
| 95 | endforeach() | 142 | endforeach() |
| @@ -0,0 +1,115 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include <gtest/gtest.h> | ||
| 12 | +#include <cmath> | ||
| 13 | +#include <limits> | ||
| 14 | +#include <type_traits> | ||
| 15 | +#include "simt_compiler_stub.h" | ||
| 16 | +#include "kernel_operator.h" | ||
| 17 | +#include "simt_api/math_functions.h" | ||
| 18 | + | ||
| 19 | +class FloatSubnormalTestsuite : public testing::Test { | ||
| 20 | +protected: | ||
| 21 | + void SetUp() {} | ||
| 22 | + void TearDown() {} | ||
| 23 | +}; | ||
| 24 | + | ||
| 25 | +TEST_F(FloatSubnormalTestsuite, ExpFloat) | ||
| 26 | +{ | ||
| 27 | + float a = 1.17549421e-38f; | ||
| 28 | + float x = 1.0f; | ||
| 29 | + float y = -80.0f; | ||
| 30 | + float subnormalOutputInput = -90.0f; | ||
| 31 | + float z = 0.0f; | ||
| 32 | + EXPECT_FLOAT_EQ(std::exp(x), expf(x)); | ||
| 33 | + EXPECT_FLOAT_EQ(std::exp(a), expf(a)); | ||
| 34 | + EXPECT_FLOAT_EQ(std::exp(y), expf(y)); | ||
| 35 | +#ifdef __ASC_FTZ__ | ||
| 36 | + EXPECT_FLOAT_EQ(std::exp(subnormalOutputInput), expf(subnormalOutputInput)); | ||
| 37 | +#else | ||
| 38 | + EXPECT_NEAR(std::exp(subnormalOutputInput), expf(subnormalOutputInput), 1e-43f); | ||
| 39 | +#endif | ||
| 40 | + EXPECT_FLOAT_EQ(std::exp(z), expf(z)); | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +TEST_F(FloatSubnormalTestsuite, InternalExpFloat) | ||
| 44 | +{ | ||
| 45 | + volatile float normalInput = -80.0f; | ||
| 46 | + volatile float subnormalOutputInput = -90.0f; | ||
| 47 | + EXPECT_FLOAT_EQ(std::exp(static_cast<float>(normalInput)), __internal_expf(normalInput)); | ||
| 48 | +#ifdef __ASC_FTZ__ | ||
| 49 | + EXPECT_FLOAT_EQ(std::exp(static_cast<float>(subnormalOutputInput)), __internal_expf(subnormalOutputInput)); | ||
| 50 | +#else | ||
| 51 | + EXPECT_NEAR(std::exp(static_cast<float>(subnormalOutputInput)), __internal_expf(subnormalOutputInput), 1e-43f); | ||
| 52 | +#endif | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +TEST_F(FloatSubnormalTestsuite, SqrtFloat) | ||
| 56 | +{ | ||
| 57 | + float x = 1.0f; | ||
| 58 | + float y = 1.17549421e-38f; | ||
| 59 | + float z = 0.0f; | ||
| 60 | + float normal = 4.0f; | ||
| 61 | + EXPECT_FLOAT_EQ(std::sqrt(x), sqrtf(x)); | ||
| 62 | +#ifdef __ASC_FTZ__ | ||
| 63 | + EXPECT_FLOAT_EQ(std::sqrt(y), sqrtf(y)); | ||
| 64 | +#else | ||
| 65 | + EXPECT_NEAR(std::sqrt(y), sqrtf(y), 1e-24f); | ||
| 66 | +#endif | ||
| 67 | + EXPECT_FLOAT_EQ(std::sqrt(z), sqrtf(z)); | ||
| 68 | +#ifdef __ASC_PREC_SQRT__ | ||
| 69 | + float scaledNormal = 0.25f; | ||
| 70 | + EXPECT_NEAR(std::sqrt(scaledNormal), sqrtf(scaledNormal), 1e-6f); | ||
| 71 | + EXPECT_NEAR(std::sqrt(normal), sqrtf(normal), 1e-6f); | ||
| 72 | + EXPECT_TRUE(std::isinf(sqrtf(ASCRT_INF_F))); | ||
| 73 | +#else | ||
| 74 | + EXPECT_FLOAT_EQ(std::sqrt(normal), sqrtf(normal)); | ||
| 75 | +#endif | ||
| 76 | +} | ||
| 77 | + | ||
| 78 | +TEST_F(FloatSubnormalTestsuite, InternalSqrtFloat) | ||
| 79 | +{ | ||
| 80 | + volatile float subnormal = std::numeric_limits<float>::denorm_min(); | ||
| 81 | + volatile float normal = 4.0f; | ||
| 82 | +#ifdef __ASC_PREC_SQRT__ | ||
| 83 | + volatile float zero = 0.0f; | ||
| 84 | + volatile float inf = ASCRT_INF_F; | ||
| 85 | + volatile float scaledNormal = 0.25f; | ||
| 86 | + EXPECT_FLOAT_EQ(0.0f, __internal_sqrtf(zero)); | ||
| 87 | + EXPECT_TRUE(std::isinf(__internal_sqrtf(inf))); | ||
| 88 | +#ifdef __ASC_FTZ__ | ||
| 89 | + EXPECT_FLOAT_EQ(std::sqrt(static_cast<float>(subnormal)), __internal_sqrtf(subnormal)); | ||
| 90 | +#else | ||
| 91 | + EXPECT_NEAR(std::sqrt(static_cast<float>(subnormal)), __internal_sqrtf(subnormal), 1e-24f); | ||
| 92 | +#endif | ||
| 93 | + EXPECT_NEAR(std::sqrt(static_cast<float>(scaledNormal)), __internal_sqrtf(scaledNormal), 1e-6f); | ||
| 94 | + EXPECT_NEAR(std::sqrt(static_cast<float>(normal)), __internal_sqrtf(normal), 1e-6f); | ||
| 95 | +#else | ||
| 96 | +#ifdef __ASC_FTZ__ | ||
| 97 | + EXPECT_FLOAT_EQ(std::sqrt(static_cast<float>(subnormal)), __internal_sqrtf(subnormal)); | ||
| 98 | +#else | ||
| 99 | + EXPECT_NEAR(std::sqrt(static_cast<float>(subnormal)), __internal_sqrtf(subnormal), 1e-24f); | ||
| 100 | +#endif | ||
| 101 | + EXPECT_FLOAT_EQ(std::sqrt(static_cast<float>(normal)), __internal_sqrtf(normal)); | ||
| 102 | +#endif | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +TEST_F(FloatSubnormalTestsuite, InternalPreciseSqrtFloatCommon) | ||
| 106 | +{ | ||
| 107 | + volatile float zero = 0.0f; | ||
| 108 | + volatile float inf = ASCRT_INF_F; | ||
| 109 | + volatile float scaled = 0.25f; | ||
| 110 | + volatile float normal = 4.0f; | ||
| 111 | + EXPECT_FLOAT_EQ(0.0f, __internal_sqrtf_precise_impl(zero)); | ||
| 112 | + EXPECT_TRUE(std::isinf(__internal_sqrtf_precise_impl(inf))); | ||
| 113 | + EXPECT_NEAR(std::sqrt(static_cast<float>(scaled)), __internal_sqrtf_precise_impl(scaled), 1e-6f); | ||
| 114 | + EXPECT_NEAR(std::sqrt(static_cast<float>(normal)), __internal_sqrtf_precise_impl(normal), 1e-6f); | ||
| 115 | +} | ||
| @@ -117,6 +117,10 @@ basic_test_five_targets=( | |||
| 117 | ascendc_run_all_tensor_api_header_checks_npu | 117 | ascendc_run_all_tensor_api_header_checks_npu |
| 118 | ascendc_run_all_tensor_api_header_checks_npu_single | 118 | ascendc_run_all_tensor_api_header_checks_npu_single |
| 119 | ascendc_ut_simt_api_ascend950pr_9599 | 119 | ascendc_ut_simt_api_ascend950pr_9599 |
| 120 | + ascendc_ut_simt_subnormal_ftz_false_prec_false | ||
| 121 | + ascendc_ut_simt_subnormal_ftz_false_prec_true | ||
| 122 | + ascendc_ut_simt_subnormal_ftz_true_prec_false | ||
| 123 | + ascendc_ut_simt_subnormal_ftz_true_prec_true | ||
| 120 | ) | 124 | ) |
| 121 | 125 | ||
| 122 | arm_test_targets=( | 126 | arm_test_targets=( |
| @@ -124,6 +128,10 @@ arm_test_targets=( | |||
| 124 | ascendc_ut_elf_tool | 128 | ascendc_ut_elf_tool |
| 125 | ascendc_ut_pack_kernel | 129 | ascendc_ut_pack_kernel |
| 126 | ascendc_ut_simt_api_ascend950pr_9599 | 130 | ascendc_ut_simt_api_ascend950pr_9599 |
| 131 | + ascendc_ut_simt_subnormal_ftz_false_prec_false | ||
| 132 | + ascendc_ut_simt_subnormal_ftz_false_prec_true | ||
| 133 | + ascendc_ut_simt_subnormal_ftz_true_prec_false | ||
| 134 | + ascendc_ut_simt_subnormal_ftz_true_prec_true | ||
| 127 | ascendc_run_all_host_header_checks | 135 | ascendc_run_all_host_header_checks |
| 128 | ascendc_run_all_host_header_checks_npu | 136 | ascendc_run_all_host_header_checks_npu |
| 129 | ascendc_run_all_host_header_checks_npu_single | 137 | ascendc_run_all_host_header_checks_npu_single |


级别:一般 问题:__internal_sqrtf_precise_impl 仅对 0 和 +Inf 提前返回,未显式处理负数与 NaN;负数会进入 x<1.0f 缩放分支,结果依赖 __sqrtf(负数) 的底层行为 影响:若硬件 __sqrtf 对负数不返回 NaN,后续 fmaf 精化会输出看似合法的有限垃圾值而非 NaN,违反 IEEE754 且错误难以察觉 修复建议:在缩放前增加负数与 NaN 守卫(如 if (x < 0.0f) return NaN),并补充负数/NaN 测试用例