CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
650 lines
27 KiB
C++
650 lines
27 KiB
C++
/*******************************************************************************
|
|
*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2023 Advanced Micro Devices, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*******************************************************************************/
|
|
#pragma once
|
|
#include "random.hpp"
|
|
|
|
#include <miopen/miopen.h>
|
|
#include <miopen/solver_id.hpp>
|
|
#include <miopen/batchnorm/problem_description.hpp>
|
|
#include <serialize.hpp>
|
|
#include <fusionHost.hpp>
|
|
|
|
#include "tensor_util.hpp"
|
|
#include "get_handle.hpp"
|
|
|
|
#define WORKAROUND_SWDEV_549725 1
|
|
|
|
struct BN2DTestCase
|
|
{
|
|
size_t N;
|
|
size_t C;
|
|
size_t H;
|
|
size_t W;
|
|
miopen::batchnorm::Direction Direction;
|
|
bool save;
|
|
bool keepRunning;
|
|
|
|
friend std::ostream& operator<<(std::ostream& ss, const BN2DTestCase& tc)
|
|
{
|
|
return ss << "(N: " << tc.N << " C:" << tc.C << " H:" << tc.H << " W:" << tc.W
|
|
<< " Direction: " << static_cast<int>(tc.Direction) << " save: " << tc.save
|
|
<< " keepRunning: " << tc.keepRunning;
|
|
}
|
|
std::vector<size_t> GetInput() const { return {N, C, H, W}; }
|
|
};
|
|
|
|
struct BN3DTestCase
|
|
{
|
|
size_t N;
|
|
size_t C;
|
|
size_t D;
|
|
size_t H;
|
|
size_t W;
|
|
miopen::batchnorm::Direction Direction;
|
|
bool save;
|
|
bool keepRunning;
|
|
|
|
friend std::ostream& operator<<(std::ostream& ss, const BN3DTestCase& tc)
|
|
{
|
|
return ss << "(N: " << tc.N << " C:" << tc.C << " D:" << tc.D << " H:" << tc.H
|
|
<< " W:" << tc.W << " Direction: " << static_cast<int>(tc.Direction)
|
|
<< " save: " << tc.save << " keepRunning: " << tc.keepRunning;
|
|
}
|
|
std::vector<size_t> GetInput() const { return {N, C, D, H, W}; }
|
|
};
|
|
|
|
template <typename T>
|
|
std::vector<T> Network2DSmall();
|
|
|
|
template <typename T>
|
|
std::vector<T> Network2DLarge();
|
|
|
|
template <typename T>
|
|
std::vector<T> Network3DBN();
|
|
|
|
template <typename T>
|
|
std::vector<T> Network3DSerialCase();
|
|
|
|
template <typename T>
|
|
std::vector<T> Network2DInvalidTraining();
|
|
|
|
template <typename T>
|
|
std::vector<T> Network3DInvalidTraining();
|
|
|
|
template <>
|
|
inline std::vector<BN2DTestCase> Network2DLarge()
|
|
{
|
|
// pyt_mlperf_resnet50v1.5
|
|
// clang-format off
|
|
return {
|
|
{64, 1, 1024, 1024, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{192, 1, 8, 8, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{12, 40, 122, 122, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{64, 256, 14, 14, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 256, 14, 14, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{64, 256, 14, 14, miopen::batchnorm::Direction::ForwardInference, 1, 0},
|
|
{64, 256, 28, 28, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 256, 28, 28, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{64, 256, 28, 28, miopen::batchnorm::Direction::ForwardInference, 1, 0},
|
|
{64, 256, 56, 56, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 256, 56, 56, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{64, 256, 56, 56, miopen::batchnorm::Direction::ForwardInference, 1, 0},
|
|
{64, 512, 14, 14, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 512, 14, 14, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{64, 512, 14, 14, miopen::batchnorm::Direction::ForwardInference, 1, 0},
|
|
{64, 512, 28, 28, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 512, 28, 28, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{64, 512, 28, 28, miopen::batchnorm::Direction::ForwardInference, 1, 0},
|
|
{64, 512, 7, 7, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 512, 7, 7, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{64, 512, 7, 7, miopen::batchnorm::Direction::ForwardInference, 1, 0},
|
|
{64, 64, 112, 112, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 64, 112, 112, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{64, 64, 112, 112, miopen::batchnorm::Direction::ForwardInference, 1, 0},
|
|
{64, 64, 56, 56, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 64, 56, 56, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{64, 64, 56, 56, miopen::batchnorm::Direction::ForwardInference, 1, 0},
|
|
{64, 2048, 7, 7, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{64, 2048, 17, 17, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{128, 256, 14, 14, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{128, 256, 16, 16, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{670, 1, 224, 224, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
{768, 1, 14, 14, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{768, 1, 23, 23, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{832, 1, 14, 14, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{832, 1, 28, 28, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
// {1, 512, 7, 7, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
// {1, 512, 7, 7, miopen::batchnorm::Direction::Backward, 1, 1},
|
|
// edge cases
|
|
{69328, 1, 22, 22, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
{69328, 1, 13, 79, miopen::batchnorm::Direction::ForwardTraining, 1, 1},
|
|
// Forward passes that should select variant 3 according to the current heuristic in common_spatial.hpp:DefaultConfigSpatialSingle and layout NCHW
|
|
{16, 1, 32, 32, miopen::batchnorm::Direction::ForwardTraining, 1, 1}
|
|
};
|
|
// clang-format on
|
|
}
|
|
|
|
// These are very large tensors which caused memory insufficient error
|
|
// when ran parallely by ctest. Hence, these are run serially.
|
|
// Shape: (2, 2048, 16, 128, 128) --> Size: 1.07e+09
|
|
// For now any test case with tensor size greater then 1e09 need to be run serially.
|
|
template <>
|
|
inline std::vector<BN3DTestCase> Network3DSerialCase()
|
|
{
|
|
// clang-format off
|
|
return {
|
|
// TODO: fix numeric issues before re-enabling large test
|
|
#ifndef WORKAROUND_SWDEV_549725
|
|
{2, 2048, 16, 128, 128, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
#endif
|
|
{2, 128, 16, 128, 128, miopen::batchnorm::Direction::Backward, 0, 1},
|
|
};
|
|
// clang-format on
|
|
}
|
|
|
|
template <>
|
|
inline std::vector<BN2DTestCase> Network2DSmall()
|
|
{
|
|
// pyt_mlperf_resnet50v1.5
|
|
// clang-format off
|
|
return {
|
|
{12, 40, 122, 122, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{16, 8, 132, 28, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{192, 2, 8, 8, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{16, 8, 56, 56, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{16, 8, 128, 256, miopen::batchnorm::Direction::ForwardTraining, 1, 0},
|
|
// Edge cases - minimum valid dimensions for Spatial BN training (N*H*W > 1)
|
|
{2, 256, 1, 1, miopen::batchnorm::Direction::ForwardTraining, 1, 0}, // N*H*W = 2 (min batch)
|
|
{2, 256, 1, 1, miopen::batchnorm::Direction::Backward, 1, 0}, // N*H*W = 2 (min spatial)
|
|
};
|
|
// clang-format on
|
|
}
|
|
|
|
template <>
|
|
inline std::vector<BN3DTestCase> Network3DBN()
|
|
{
|
|
// clang-format off
|
|
return {
|
|
{2, 2, 3, 224, 224, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{16, 8, 132, 28, 28, miopen::batchnorm::Direction::Backward, 1, 0},
|
|
{16, 8, 16, 128, 128, miopen::batchnorm::Direction::ForwardTraining, 1, 0},
|
|
// Edge cases - minimum valid dimensions for Spatial BN training (N*D*H*W > 1)
|
|
{2, 256, 1, 1, 1, miopen::batchnorm::Direction::ForwardTraining, 1, 0}, // N*D*H*W = 2 (min batch)
|
|
{2, 256, 1, 1, 1, miopen::batchnorm::Direction::Backward, 1, 0}, // N*D*H*W = 2 (min spatial D)
|
|
};
|
|
// clang-format on
|
|
}
|
|
|
|
// Invalid training cases for validation testing (PyTorch rejects these)
|
|
// These should only be used by validation tests that expect API rejection
|
|
template <>
|
|
inline std::vector<BN2DTestCase> Network2DInvalidTraining()
|
|
{
|
|
// clang-format off
|
|
return {
|
|
// N*H*W = 1 cases (invalid for Spatial BN training)
|
|
{1, 256, 1, 1, miopen::batchnorm::Direction::ForwardTraining, 0, 0}, // Should be rejected
|
|
{1, 256, 1, 1, miopen::batchnorm::Direction::Backward, 0, 0}, // Should be rejected
|
|
};
|
|
// clang-format on
|
|
}
|
|
|
|
template <>
|
|
inline std::vector<BN3DTestCase> Network3DInvalidTraining()
|
|
{
|
|
// clang-format off
|
|
return {
|
|
// N*D*H*W = 1 cases (invalid for Spatial BN training)
|
|
{1, 256, 1, 1, 1, miopen::batchnorm::Direction::ForwardTraining, 0, 0}, // Should be rejected
|
|
{1, 256, 1, 1, 1, miopen::batchnorm::Direction::Backward, 0, 0}, // Should be rejected
|
|
};
|
|
// clang-format on
|
|
}
|
|
|
|
template <typename XDataType, typename YDataType, typename AccDataType, typename TConfig>
|
|
struct BNTestData
|
|
{
|
|
void
|
|
SetUpImpl(const TConfig& config, miopenBatchNormMode_t t_bnmode, miopenTensorLayout_t t_layout)
|
|
{
|
|
bn_config = config;
|
|
tensor_layout = t_layout;
|
|
bn_mode = t_bnmode;
|
|
CreateTensors();
|
|
InitTensorsWithRandValue();
|
|
SetDirection();
|
|
WriteToGPU();
|
|
}
|
|
const miopen::TensorDescriptor& GetInputDesc() const { return input.desc; }
|
|
|
|
tensor<XDataType> input;
|
|
tensor<YDataType> output;
|
|
tensor<AccDataType> out_ref;
|
|
miopen::Allocator::ManageDataPtr in_dev;
|
|
miopen::Allocator::ManageDataPtr out_dev;
|
|
|
|
miopen::FusionPlanDescriptor fusePlanDesc;
|
|
miopen::OperatorArgs params;
|
|
miopen::TensorDescriptor bn_desc;
|
|
miopenBatchNormMode_t bn_mode;
|
|
miopen::batchnorm::Direction direction;
|
|
miopenTensorLayout_t tensor_layout;
|
|
TConfig bn_config;
|
|
|
|
private:
|
|
void CreateTensors()
|
|
{
|
|
input = tensor<XDataType>{tensor_layout, bn_config.GetInput()};
|
|
output = tensor<YDataType>{tensor_layout, bn_config.GetInput()};
|
|
out_ref = tensor<AccDataType>{tensor_layout, bn_config.GetInput()};
|
|
}
|
|
|
|
void InitTensorsWithRandValue()
|
|
{
|
|
// -2.0 to 2.0
|
|
input.generate(uniform_signed_initializer<XDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
}
|
|
|
|
void SetDirection() { direction = bn_config.Direction; }
|
|
void WriteToGPU()
|
|
{
|
|
auto&& handle = get_handle();
|
|
in_dev = handle.Write(input.data);
|
|
out_dev = handle.Write(output.data);
|
|
}
|
|
};
|
|
|
|
template <typename XDataType,
|
|
typename YDataType,
|
|
typename ScaleDataType,
|
|
typename BiasDataType,
|
|
typename MeanVarDataType,
|
|
typename AccDataType,
|
|
typename TConfig>
|
|
struct BNInferTestData : public BNTestData<XDataType, YDataType, AccDataType, TConfig>
|
|
{
|
|
void SetUpImpl(const TConfig& config,
|
|
miopenBatchNormMode_t t_bnmode,
|
|
miopenTensorLayout_t t_layout,
|
|
bool useInverseVariance_)
|
|
{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::SetUpImpl(
|
|
config, t_bnmode, t_layout);
|
|
useInverseVariance = useInverseVariance_;
|
|
CreateTensors();
|
|
InitTensorsWithRandValue();
|
|
WriteToGPU();
|
|
}
|
|
|
|
tensor<ScaleDataType> scale;
|
|
tensor<BiasDataType> shift;
|
|
tensor<MeanVarDataType> estMean;
|
|
tensor<MeanVarDataType> estVariance;
|
|
miopen::Allocator::ManageDataPtr scale_dev;
|
|
miopen::Allocator::ManageDataPtr shift_dev;
|
|
miopen::Allocator::ManageDataPtr estMean_dev;
|
|
miopen::Allocator::ManageDataPtr estVariance_dev;
|
|
double epsilon{1.0e-5};
|
|
float alpha{1.0f};
|
|
float beta{0.0f};
|
|
double activ_alpha;
|
|
double activ_beta;
|
|
miopenActivationMode_t activ_mode;
|
|
bool useInverseVariance = false;
|
|
|
|
private:
|
|
void CreateTensors()
|
|
{
|
|
auto derivedBnDesc = miopen::TensorDescriptor{};
|
|
miopen::DeriveBNTensorDescriptor(
|
|
derivedBnDesc,
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::input.desc,
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::bn_mode);
|
|
scale = tensor<ScaleDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
shift = tensor<BiasDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
estMean = tensor<MeanVarDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
estVariance = tensor<MeanVarDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
}
|
|
|
|
void InitTensorsWithRandValue()
|
|
{
|
|
// -2.0 to 2.0
|
|
scale.generate(uniform_signed_initializer<ScaleDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
shift.generate(uniform_signed_initializer<BiasDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
estMean.generate(
|
|
uniform_signed_initializer<MeanVarDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
if(useInverseVariance)
|
|
{
|
|
// Given an epsilon of 1e-5, the max value is 1/sqrt(epsilon) ==> 316.228
|
|
// Given a max variance of 2, the min value is 1/sqrt(epsilon + 2.0) ==> 0.7
|
|
estVariance.generate(uniform_unsigned_initializer<MeanVarDataType>(0.7, 317));
|
|
}
|
|
else
|
|
{
|
|
// estVaraince has to be +ve number otherwise 1/sqrt(-ve) would
|
|
// give img number
|
|
estVariance.generate(
|
|
uniform_unsigned_initializer<MeanVarDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
}
|
|
}
|
|
void WriteToGPU()
|
|
{
|
|
auto&& handle = get_handle();
|
|
scale_dev = handle.Write(scale.data);
|
|
shift_dev = handle.Write(shift.data);
|
|
estMean_dev = handle.Write(estMean.data);
|
|
estVariance_dev = handle.Write(estVariance.data);
|
|
}
|
|
};
|
|
|
|
template <typename XDataType,
|
|
typename DxDataType,
|
|
typename DyDataType,
|
|
typename ScaleDataType,
|
|
typename DscaleDbiasDataType,
|
|
typename MeanVarDataType,
|
|
typename AccDataType,
|
|
typename TConfig>
|
|
struct BNBwdTestData : public BNTestData<XDataType, DyDataType, AccDataType, TConfig>
|
|
{
|
|
void
|
|
SetUpImpl(const TConfig& config, miopenBatchNormMode_t t_bnmode, miopenTensorLayout_t t_layout)
|
|
{
|
|
BNTestData<XDataType, DxDataType, AccDataType, TConfig>::SetUpImpl(
|
|
config, t_bnmode, t_layout);
|
|
CreateTensors();
|
|
InitTensorsWithRandValue();
|
|
WriteToGPU();
|
|
}
|
|
|
|
tensor<ScaleDataType> bnScale;
|
|
tensor<ScaleDataType> bnBias;
|
|
|
|
tensor<MeanVarDataType> savedMean;
|
|
tensor<MeanVarDataType> savedInvVar;
|
|
|
|
tensor<DyDataType> dy;
|
|
tensor<DscaleDbiasDataType> dScale;
|
|
tensor<DscaleDbiasDataType> dBias;
|
|
tensor<AccDataType> dScale_ref;
|
|
tensor<AccDataType> dBias_ref;
|
|
|
|
miopen::Allocator::ManageDataPtr bnScale_dev;
|
|
miopen::Allocator::ManageDataPtr bnBias_dev;
|
|
miopen::Allocator::ManageDataPtr savedMean_dev;
|
|
miopen::Allocator::ManageDataPtr savedInvVar_dev;
|
|
|
|
miopen::Allocator::ManageDataPtr dy_dev;
|
|
miopen::Allocator::ManageDataPtr dScale_dev;
|
|
miopen::Allocator::ManageDataPtr dBias_dev;
|
|
miopen::Allocator::ManageDataPtr dScale_ref_dev;
|
|
miopen::Allocator::ManageDataPtr dBias_ref_dev;
|
|
double epsilon = std::numeric_limits<float>::epsilon();
|
|
|
|
float alphaDataDiff{1.0f}, betaDataDiff{0.0f};
|
|
float alphaParamDiff{1.0f}, betaParamDiff{0.0f};
|
|
|
|
double activ_alpha;
|
|
double activ_beta;
|
|
miopenActivationMode_t activ_mode;
|
|
|
|
private:
|
|
void CreateTensors()
|
|
{
|
|
dy = tensor<DyDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::bn_config.GetInput()};
|
|
|
|
auto derivedBnDesc = miopen::TensorDescriptor{};
|
|
miopen::DeriveBNTensorDescriptor(
|
|
derivedBnDesc,
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::input.desc,
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::bn_mode);
|
|
bnScale = tensor<ScaleDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
bnBias = tensor<ScaleDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
savedMean = tensor<MeanVarDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
savedInvVar = tensor<MeanVarDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
dScale = tensor<DscaleDbiasDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
dBias = tensor<DscaleDbiasDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
dScale_ref = tensor<AccDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
dBias_ref = tensor<AccDataType>{
|
|
BNTestData<XDataType, DyDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
}
|
|
|
|
void InitTensorsWithRandValue()
|
|
{
|
|
dy.generate(uniform_signed_initializer<DyDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
bnScale.generate(uniform_signed_initializer<ScaleDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
bnBias.generate(uniform_signed_initializer<ScaleDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
savedMean.generate(
|
|
uniform_signed_initializer<MeanVarDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
savedInvVar.generate(
|
|
uniform_signed_initializer<MeanVarDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
|
|
std::fill(dScale.begin(), dScale.end(), 0.);
|
|
std::fill(dBias.begin(), dBias.end(), 0.);
|
|
|
|
std::fill(dScale_ref.begin(), dScale_ref.end(), 0.);
|
|
std::fill(dBias_ref.begin(), dBias_ref.end(), 0.);
|
|
}
|
|
void WriteToGPU()
|
|
{
|
|
auto&& handle = get_handle();
|
|
|
|
bnScale_dev = handle.Write(bnScale.data);
|
|
bnBias_dev = handle.Write(bnBias.data);
|
|
savedMean_dev = handle.Write(savedMean.data);
|
|
savedInvVar_dev = handle.Write(savedInvVar.data);
|
|
dy_dev = handle.Write(dy.data);
|
|
|
|
dScale_dev = handle.Write(dScale.data);
|
|
dBias_dev = handle.Write(dBias.data);
|
|
}
|
|
};
|
|
|
|
template <typename XDataType,
|
|
typename YDataType,
|
|
typename ScaleDataType,
|
|
typename BiasDataType,
|
|
typename RunSaveDataType,
|
|
typename AccDataType,
|
|
typename TConfig>
|
|
struct BNFwdTrainTestData : public BNTestData<XDataType, YDataType, AccDataType, TConfig>
|
|
{
|
|
void
|
|
SetUpImpl(const TConfig& config, miopenBatchNormMode_t t_bnmode, miopenTensorLayout_t t_layout)
|
|
{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::SetUpImpl(
|
|
config, t_bnmode, t_layout);
|
|
CreateTensors();
|
|
InitTensorsWithRandValue();
|
|
WriteToGPU();
|
|
}
|
|
|
|
tensor<ScaleDataType> scale;
|
|
tensor<BiasDataType> shift;
|
|
tensor<RunSaveDataType> saveMean;
|
|
tensor<RunSaveDataType> saveVariance;
|
|
tensor<RunSaveDataType> runMean;
|
|
tensor<RunSaveDataType> runVariance;
|
|
// V3 API: separate prev/next buffers for ping-pong
|
|
tensor<RunSaveDataType> prevRunMean;
|
|
tensor<RunSaveDataType> prevRunVariance;
|
|
tensor<RunSaveDataType> nextRunMean;
|
|
tensor<RunSaveDataType> nextRunVariance;
|
|
|
|
tensor<AccDataType> saveMean_ref;
|
|
tensor<AccDataType> saveVariance_ref;
|
|
tensor<AccDataType> runMean_ref;
|
|
tensor<AccDataType> runVariance_ref;
|
|
|
|
miopen::Allocator::ManageDataPtr scale_dev;
|
|
miopen::Allocator::ManageDataPtr shift_dev; // bias
|
|
miopen::Allocator::ManageDataPtr saveMean_dev;
|
|
miopen::Allocator::ManageDataPtr saveVariance_dev;
|
|
miopen::Allocator::ManageDataPtr runMean_dev;
|
|
miopen::Allocator::ManageDataPtr runVariance_dev;
|
|
// V3 API: separate prev/next device buffers
|
|
miopen::Allocator::ManageDataPtr prevRunMean_dev;
|
|
miopen::Allocator::ManageDataPtr prevRunVariance_dev;
|
|
miopen::Allocator::ManageDataPtr nextRunMean_dev;
|
|
miopen::Allocator::ManageDataPtr nextRunVariance_dev;
|
|
double epsilon = 1.0e-5;
|
|
double averageFactor = 0.1;
|
|
float alpha = 1.0f;
|
|
float beta = 0.0f;
|
|
double activ_alpha;
|
|
double activ_beta;
|
|
miopenActivationMode_t activ_mode;
|
|
|
|
private:
|
|
void CreateTensors()
|
|
{
|
|
auto derivedBnDesc = miopen::TensorDescriptor{};
|
|
miopen::DeriveBNTensorDescriptor(
|
|
derivedBnDesc,
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::input.desc,
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::bn_mode);
|
|
scale = tensor<ScaleDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
shift = tensor<BiasDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
saveMean = tensor<RunSaveDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
saveVariance = tensor<RunSaveDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
runMean = tensor<RunSaveDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
runVariance = tensor<RunSaveDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
// V3 API: separate prev/next buffers
|
|
prevRunMean = tensor<RunSaveDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
prevRunVariance = tensor<RunSaveDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
nextRunMean = tensor<RunSaveDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
nextRunVariance = tensor<RunSaveDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
// ref
|
|
saveMean_ref = tensor<AccDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
saveVariance_ref = tensor<AccDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
runMean_ref = tensor<AccDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
runVariance_ref = tensor<AccDataType>{
|
|
BNTestData<XDataType, YDataType, AccDataType, TConfig>::tensor_layout,
|
|
derivedBnDesc.GetLengths()};
|
|
}
|
|
|
|
void InitTensorsWithRandValue()
|
|
{
|
|
// -2.0 to 2.0
|
|
scale.generate(uniform_signed_initializer<ScaleDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
shift.generate(uniform_signed_initializer<BiasDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
runMean.generate(
|
|
uniform_signed_initializer<RunSaveDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
runVariance.generate(
|
|
uniform_signed_initializer<RunSaveDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
// V3 API: initialize prev buffers with same values as runMean/runVariance
|
|
prevRunMean.generate(
|
|
uniform_signed_initializer<RunSaveDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
prevRunVariance.generate(
|
|
uniform_signed_initializer<RunSaveDataType>(2e-3 /*scale*/, 1000 /*range*/));
|
|
// nextRunMean and nextRunVariance will be output buffers (don't need initialization)
|
|
|
|
std::transform(saveMean.data.begin(),
|
|
saveMean.data.end(),
|
|
saveMean_ref.data.begin(),
|
|
[](float val) { return static_cast<AccDataType>(val); });
|
|
std::transform(saveVariance.data.begin(),
|
|
saveVariance.data.end(),
|
|
saveVariance_ref.data.begin(),
|
|
[](float val) { return static_cast<AccDataType>(val); });
|
|
std::transform(runMean.data.begin(),
|
|
runMean.data.end(),
|
|
runMean_ref.data.begin(),
|
|
[](float val) { return static_cast<AccDataType>(val); });
|
|
std::transform(runVariance.data.begin(),
|
|
runVariance.data.end(),
|
|
runVariance_ref.data.begin(),
|
|
[](float val) { return static_cast<AccDataType>(val); });
|
|
}
|
|
void WriteToGPU()
|
|
{
|
|
auto&& handle = get_handle();
|
|
scale_dev = handle.Write(scale.data);
|
|
shift_dev = handle.Write(shift.data);
|
|
saveMean_dev = handle.Write(saveMean.data);
|
|
saveVariance_dev = handle.Write(saveVariance.data);
|
|
runMean_dev = handle.Write(runMean.data);
|
|
runVariance_dev = handle.Write(runVariance.data);
|
|
// V3 API: write prev buffers to GPU
|
|
prevRunMean_dev = handle.Write(prevRunMean.data);
|
|
prevRunVariance_dev = handle.Write(prevRunVariance.data);
|
|
// Allocate next buffers (output only, no need to initialize data)
|
|
nextRunMean_dev = handle.Create<RunSaveDataType>(prevRunMean.data.size());
|
|
nextRunVariance_dev = handle.Create<RunSaveDataType>(prevRunVariance.data.size());
|
|
}
|
|
};
|