// Copyright © Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #pragma once #include "ConvShapeCase.hpp" #include #include #include #include #include #include #include #include #include // ============================================================================ // Shared infrastructure for weight-gradient (wgrad) GPU-vs-CPU reference tests. // ============================================================================ namespace gpu_conv_wgrad_ref_test { using namespace hipdnn_data_sdk::utilities; using namespace hipdnn_data_sdk::types; using namespace hipdnn_test_sdk::utilities; using namespace hipdnn_gpu_ref; using gpu_conv_ref_test::assertAllClose; using gpu_conv_ref_test::ConvShapeCase; using ConvWgradShapeCase = ConvShapeCase; // Core helper: fills x and dy tensors, runs GPU and CPU wgrad, compares dw results. // For wgrad: x and dy are inputs, dw is the output (weight gradient). template void compareGpuVsCpuConvWrw(Tensor& xTensor, Tensor& dyTensor, Tensor& dwCpu, Tensor& dwGpu, const std::vector& strides, const std::vector& dilations, const std::vector& prePadding, const std::vector& postPadding, float tolerance, float fillRange) { const unsigned int seed = 42; xTensor.fillWithRandomValues( static_cast(-fillRange), static_cast(fillRange), seed); dyTensor.fillWithRandomValues( static_cast(-fillRange), static_cast(fillRange), seed + 1); CpuFpReferenceConvolution::wgrad( xTensor, dwCpu, dyTensor, strides, dilations, prePadding, postPadding); GpuFpReferenceConvolution::wgrad( xTensor, dwGpu, dyTensor, strides, dilations, prePadding, postPadding); assertAllClose(dwCpu, dwGpu, tolerance); } // Convenience wrapper for uniform-type wgrad tests. // When layout is non-null, x and dy use channel-last strides. // dw (weight gradient) always uses default packed (KCRS) strides. template void runGpuVsCpuConvWrw(const std::vector& xDims, const std::vector& wDims, const std::vector& dyDims, const std::vector& strides, const std::vector& dilations, const std::vector& prePadding, const std::vector& postPadding, float tolerance, const TensorLayout* layout = nullptr, float fillRange = 1.0f) { auto xTensor = layout != nullptr ? Tensor(xDims, *layout) : Tensor(xDims); auto dyTensor = layout != nullptr ? Tensor(dyDims, *layout) : Tensor(dyDims); auto dwCpu = Tensor(wDims); auto dwGpu = Tensor(wDims); compareGpuVsCpuConvWrw(xTensor, dyTensor, dwCpu, dwGpu, strides, dilations, prePadding, postPadding, tolerance, fillRange); } // ============================================================================ // ConvWgradShapeSuite — parameterized fixture for shape-based GPU-vs-CPU tests // ============================================================================ template class ConvWgradShapeSuite : public ::testing::TestWithParam { protected: static float tolerance(const ConvWgradShapeCase& tc) { constexpr double FILL_RANGE = 1.0; auto dyDims = tc.computeOutputDims(); return hipdnn_test_sdk::utilities::conv:: calculateConvWrwTolerance( -FILL_RANGE, FILL_RANGE, -FILL_RANGE, FILL_RANGE, dyDims); } void runConvWgradShapeTest() { SKIP_IF_NO_DEVICES(); const auto& tc = GetParam(); auto dyDims = tc.computeOutputDims(); runGpuVsCpuConvWrw(tc.xDims, tc.wDims, dyDims, tc.strides, tc.dilations, tc.padding, tc.padding, tolerance(tc), tc.layout); } }; } // namespace gpu_conv_wgrad_ref_test