// Copyright © Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #include #include #include #include #include #include #include #include using namespace hipdnn_data_sdk::utilities; using namespace hipdnn_flatbuffers_sdk::data_objects; using namespace hipdnn_test_sdk::utilities; using hipdnn_test_sdk::detail::safeTestTypeCast; namespace { template void fillValues(Tensor& tensor, const std::vector& values) { ASSERT_EQ(static_cast(tensor.elementCount()), values.size()); auto* data = tensor.memory().hostData(); for(size_t i = 0; i < values.size(); ++i) { data[i] = safeTestTypeCast(values[i]); } tensor.memory().markHostModified(); } template void expectTensorValues(const Tensor& tensor, const std::vector& expected) { ASSERT_EQ(static_cast(tensor.elementCount()), expected.size()); const auto* data = tensor.memory().hostData(); for(size_t i = 0; i < expected.size(); ++i) { EXPECT_FLOAT_EQ(static_cast(data[i]), expected[i]) << "Mismatch at index " << i; } } } // namespace TEST(TestCpuFpReferenceResampleFwd, MaxPoolProducesValuesAndIndices) { Tensor x({1, 1, 3, 3}); Tensor y({1, 1, 2, 2}); Tensor index({1, 1, 2, 2}); fillValues(x, {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f}); CpuFpReferenceResampleFwd::forward( x, y, {0, 0}, {1, 1}, {2, 2}, ResampleMode::MAXPOOL, PaddingMode::ZERO_PAD, &index); expectTensorValues(y, {5.0f, 6.0f, 8.0f, 9.0f}); expectTensorValues(index, {4.0f, 5.0f, 7.0f, 8.0f}); } TEST(TestCpuFpReferenceResampleFwd, AverageExcludePaddingUsesValidElementCount) { Tensor x({1, 1, 2, 2}); Tensor y({1, 1, 2, 2}); fillValues(x, {1.0f, 2.0f, 3.0f, 4.0f}); CpuFpReferenceResampleFwd::forward( x, y, {1, 1}, {1, 1}, {2, 2}, ResampleMode::AVGPOOL_EXCLUDE_PADDING, PaddingMode::ZERO_PAD); expectTensorValues(y, {1.0f, 1.5f, 2.0f, 2.5f}); } TEST(TestCpuFpReferenceResampleFwd, AverageIncludePaddingUsesWindowElementCount) { Tensor x({1, 1, 2, 2}); Tensor y({1, 1, 2, 2}); fillValues(x, {1.0f, 2.0f, 3.0f, 4.0f}); CpuFpReferenceResampleFwd::forward( x, y, {1, 1}, {1, 1}, {2, 2}, ResampleMode::AVGPOOL_INCLUDE_PADDING, PaddingMode::ZERO_PAD); expectTensorValues(y, {0.25f, 0.75f, 1.0f, 2.5f}); } TEST(TestCpuFpReferenceResampleFwd, MaxPoolNegativeInfinityPaddingIgnoresPadding) { Tensor x({1, 1, 2, 2}); Tensor y({1, 1, 2, 2}); Tensor index({1, 1, 2, 2}); fillValues(x, {-4.0f, -3.0f, -2.0f, -1.0f}); CpuFpReferenceResampleFwd::forward( x, y, {1, 1}, {1, 1}, {2, 2}, ResampleMode::MAXPOOL, PaddingMode::NEG_INF_PAD, &index); expectTensorValues(y, {-4.0f, -3.0f, -2.0f, -1.0f}); expectTensorValues(index, {0.0f, 1.0f, 2.0f, 3.0f}); } TEST(TestCpuFpReferenceResampleFwd, MaxPoolSelectsFirstLowestValue) { Tensor x({1, 1, 1, 2}); Tensor y({1, 1, 1, 1}); Tensor index({1, 1, 1, 1}); fillValues(x, {std::numeric_limits::lowest(), std::numeric_limits::lowest()}); CpuFpReferenceResampleFwd::forward( x, y, {0, 0}, {1, 1}, {1, 2}, ResampleMode::MAXPOOL, PaddingMode::ZERO_PAD, &index); expectTensorValues(y, {std::numeric_limits::lowest()}); expectTensorValues(index, {0.0f}); } TEST(TestCpuFpReferenceResampleFwd, AveragePropagatesNanAndInfinity) { Tensor x({1, 1, 1, 2}); Tensor y({1, 1, 1, 2}); auto* xData = x.memory().hostData(); xData[0] = std::numeric_limits::quiet_NaN(); xData[1] = std::numeric_limits::infinity(); x.memory().markHostModified(); CpuFpReferenceResampleFwd::forward( x, y, {0, 0}, {1, 1}, {1, 1}, ResampleMode::AVGPOOL_EXCLUDE_PADDING, PaddingMode::ZERO_PAD); EXPECT_TRUE(std::isnan(y.getHostValue({0, 0, 0, 0}))); EXPECT_EQ(y.getHostValue({0, 0, 0, 1}), std::numeric_limits::infinity()); } TEST(TestCpuFpReferenceResampleFwd, MaxPoolAllNegativeInfinityPaddingKeepsSentinel) { Tensor x({1, 1, 1, 1}); Tensor y({1, 1, 1, 1}); Tensor index({1, 1, 1, 1}); fillValues(x, {1.0f}); CpuFpReferenceResampleFwd::forward( x, y, {2, 2}, {1, 1}, {1, 1}, ResampleMode::MAXPOOL, PaddingMode::NEG_INF_PAD, &index); expectTensorValues(y, {std::numeric_limits::lowest()}); expectTensorValues(index, {-1.0f}); } TEST(TestCpuFpReferenceResampleFwd, SupportsChannelLastStrides) { Tensor x({1, 2, 3, 3}, TensorLayout::NHWC); Tensor y({1, 2, 2, 2}, TensorLayout::NHWC); fillValues(x, {1.0f, 10.0f, 2.0f, 20.0f, 3.0f, 30.0f, 4.0f, 40.0f, 5.0f, 50.0f, 6.0f, 60.0f, 7.0f, 70.0f, 8.0f, 80.0f, 9.0f, 90.0f}); CpuFpReferenceResampleFwd::forward( x, y, {0, 0}, {1, 1}, {2, 2}, ResampleMode::MAXPOOL, PaddingMode::ZERO_PAD); expectTensorValues(y, {5.0f, 50.0f, 6.0f, 60.0f, 8.0f, 80.0f, 9.0f, 90.0f}); } TEST(TestCpuFpReferenceResampleFwd, RejectsUnsupportedRanks) { const Tensor x({1, 2, 3}); Tensor y({1, 2, 2}); EXPECT_THROW((CpuFpReferenceResampleFwd::forward( x, y, {0}, {1}, {2}, ResampleMode::MAXPOOL, PaddingMode::ZERO_PAD)), std::runtime_error); }