diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp new file mode 100644 index 00000000000..bd6d0d63366 --- /dev/null +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -0,0 +1,175 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ +#include +#include +#include +#include + +namespace migraphx { +inline namespace MIGRAPHX_INLINE_NS { +namespace onnx { + +// com.microsoft.SkipSimplifiedLayerNormalization +// Skip and Root Mean Square Layer Normalization + +// Version +// This version of the operator has been available since version 1 of the 'com.microsoft' operator +// set. + +// Type Constraints +// T : tensor(float), tensor(float16) +// Constrain input and output types to float or half tensors. +// U : tensor(float) +// Constrain mean and inv_std_var to float tensors. + +struct parse_skip_simplified_layer_normalization + : op_parser +{ + std::vector operators() const { return {{"SkipLayerNormalization"}}; } + + std::vector parse(const op_desc& /*opd*/, + const onnx_parser& parser, + const onnx_parser::node_info& info, + std::vector args) const + { + // Attributes + // epsilon : float + // The epsilon value to use to avoid division by zero. + float epsilon = 1e-5f; + if(contains(info.attributes, "epsilon")) + { + epsilon = parser.parse_value(info.attributes.at("epsilon")).at(); + } + + // Inputs (3 - 5) + // input : T + // 3D input tensor with shape (batch_size, sequence_length, hidden_size) Or 2D input tensor + // with shape (token_count, hidden_size) + // skip : T + // 3D input tensor with shape (batch_size, sequence_length, hidden_size) + // Or 2D input tensor with shape (token_count, hidden_size) + // gamma : T + // 1D input tensor with shape (hidden_size) + // beta (optional) : T + // 1D skip tensor with shape (hidden_size) + // bias (optional) : T + // 1D bias tensor with shape (hidden_size) - not used by ORT + + if(args.size() < 3 or args.size() > 5) + { + MIGRAPHX_THROW("PARSE_SKIPSIMPLIFIEDLAYERNORMALIZATION: invalid input count"); + } + + auto x = args.at(0); + auto skip = args.at(1); + auto gamma = args.at(2); + + auto x_shape = x->get_shape(); + auto x_dtype = x_shape.type(); + int64_t x_rank = x_shape.ndim(); + int64_t skip_rank = skip->get_shape().ndim(); + int64_t gamma_rank = gamma->get_shape().ndim(); + // axis = hidden_size dim + int64_t axis = x_rank - 1; + + if(x_rank != 3 or (x_rank != skip_rank and skip_rank != 2) or gamma_rank != 1) + { + MIGRAPHX_THROW("PARSE_SKIPLAYERNORMALIZATION: invalid input shape"); + } + + // Beta always applied at the end result as an affine offset + instruction_ref beta; + if(args.size() >= 4) + { + beta = args.at(3); + auto beta_shape = beta->get_shape(); + auto beta_len = beta_shape.lens(); + if(beta_shape.type() != x_dtype or beta_len.size() > 1) + { + MIGRAPHX_THROW("PARSE_SKIPLAYERNORMALIZATION: Invalid Beta shape"); + } + } + + // Bias is always applied to the input along with any skip input + instruction_ref bias; + if(args.size() == 5) + { + bias = args.at(4); + auto bias_shape = bias->get_shape(); + auto bias_len = bias_shape.lens(); + if(bias_shape.type() != x_dtype or bias_len.size() > 1) + { + MIGRAPHX_THROW("PARSE_SKIPLAYERNORMALIZATION: Invalid Bias shape"); + } + } + + x = info.add_common_op("add", x, skip); + if(args.size() >= 5) + { + x = info.add_common_op("add", x, bias); + } + + // Get the mean of input and squared of the expectation (for variance calc later) + // Var = E( (x - E[x])) ^2) + auto mean = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), x); + auto pr_var = info.add_common_op("sqdiff", {x, mean}); + auto var = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), pr_var); + + epsilon = + (x_dtype == migraphx::shape::half_type and std::abs(epsilon) < 1e-7) ? 1e-7 : epsilon; + auto eps = info.add_literal(migraphx::literal{shape{x_dtype}, {epsilon}}); + + auto var_ep = info.add_common_op("add", var, eps); + + // reciprical sqrt here on resulting variance + epsilon offset to avoid div by zero + auto r_var = info.add_instruction(make_op("rsqrt"), var_ep); + + // Output is (x - E[x]) * gamma / (sqrt(var(x) - epsilon)) + beta + auto result = info.add_common_op("sub", x, mean); + result = info.add_common_op("mul", result, r_var); + result = info.add_common_op("mul", result, gamma); + + if(args.size() >= 4) + { + result = info.add_common_op("add", result, beta); + } + + // Outputs (1 - 4) + // output : T + // 3D output tensor with shape (batch_size, sequence_length, hidden_size) + // mean (optional) : U Saved mean used during training + // to speed up gradient computation + // inv_std_var (optional) : U Saved inverse standard + // variance used during training to speed up gradient computation. + // input_skip_bias_sum (optional) : T Sum of the input and skip inputs (and bias if it + // exists)with shape (batch_size, sequence_length, hidden_size) or (token_count, + // hidden_size). + + return {result, mean, r_var, x}; + } +}; + +} // namespace onnx +} // namespace MIGRAPHX_INLINE_NS +} // namespace migraphx diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index ab94d5e1be8..26545711133 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -12657,6 +12657,165 @@ def skip_simplified_layer_normalization_invalid_input_test(): return ([node], [x, skip, gamma], [y]) +@onnx_test() +def skip_layer_normalization_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT16, [2, 2, 4]) + skip = helper.make_tensor_value_info('skip', TensorProto.FLOAT16, + [2, 2, 4]) + gamma = helper.make_tensor_value_info('gamma', TensorProto.FLOAT16, [4]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT16, [2, 2, 4]) + mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [2, 2, 1]) + inv_std_var = helper.make_tensor_value_info('inv_std_var', + TensorProto.FLOAT, [2, 2, 1]) + input_skip_bias_sum = helper.make_tensor_value_info( + 'input_skip_bias_sum', TensorProto.FLOAT16, [2, 2, 4]) + + node = onnx.helper.make_node( + 'SkipLayerNormalization', + inputs=['x', 'skip', 'gamma'], + outputs=['y', 'mean', 'inv_std_var', 'input_skip_bias_sum'], + epsilon=1e-5, + domain="com.microsoft") + + return ([node], [x, skip, + gamma], [y, mean, inv_std_var, input_skip_bias_sum]) + + +@onnx_test() +def skip_layer_normalization_beta_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT16, [2, 2, 4]) + skip = helper.make_tensor_value_info('skip', TensorProto.FLOAT16, + [2, 2, 4]) + gamma = helper.make_tensor_value_info('gamma', TensorProto.FLOAT16, [4]) + beta = helper.make_tensor_value_info('beta', TensorProto.FLOAT16, [4]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT16, [2, 2, 4]) + mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [2, 2, 1]) + inv_std_var = helper.make_tensor_value_info('inv_std_var', + TensorProto.FLOAT, [2, 2, 1]) + input_skip_bias_sum = helper.make_tensor_value_info( + 'input_skip_bias_sum', TensorProto.FLOAT16, [2, 2, 4]) + + node = onnx.helper.make_node( + 'SkipLayerNormalization', + inputs=['x', 'skip', 'gamma', 'beta'], + outputs=['y', 'mean', 'inv_std_var', 'input_skip_bias_sum'], + epsilon=1e-5, + domain="com.microsoft") + + return ([node], [x, skip, gamma, + beta], [y, mean, inv_std_var, input_skip_bias_sum]) + + +@onnx_test() +def skip_layer_normalization_bad_beta_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT16, [2, 2, 4]) + skip = helper.make_tensor_value_info('skip', TensorProto.FLOAT16, + [2, 2, 4]) + gamma = helper.make_tensor_value_info('gamma', TensorProto.FLOAT16, [4]) + beta = helper.make_tensor_value_info('beta', TensorProto.FLOAT16, [4, 4]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT16, [2, 2, 4]) + mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [2, 2, 1]) + inv_std_var = helper.make_tensor_value_info('inv_std_var', + TensorProto.FLOAT, [2, 2, 1]) + input_skip_bias_sum = helper.make_tensor_value_info( + 'input_skip_bias_sum', TensorProto.FLOAT16, [2, 2, 4]) + + node = onnx.helper.make_node( + 'SkipLayerNormalization', + inputs=['x', 'skip', 'gamma', 'beta'], + outputs=['y', 'mean', 'inv_std_var', 'input_skip_bias_sum'], + epsilon=1e-5, + domain="com.microsoft") + + return ([node], [x, skip, gamma, + beta], [y, mean, inv_std_var, input_skip_bias_sum]) + + +@onnx_test() +def skip_layer_normalization_beta_bias_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT16, [2, 2, 4]) + skip = helper.make_tensor_value_info('skip', TensorProto.FLOAT16, + [2, 2, 4]) + gamma = helper.make_tensor_value_info('gamma', TensorProto.FLOAT16, [4]) + beta = helper.make_tensor_value_info('beta', TensorProto.FLOAT16, [4]) + bias = helper.make_tensor_value_info('bias', TensorProto.FLOAT16, [4]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT16, [2, 2, 4]) + mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [2, 2, 1]) + inv_std_var = helper.make_tensor_value_info('inv_std_var', + TensorProto.FLOAT, [2, 2, 1]) + input_skip_bias_sum = helper.make_tensor_value_info( + 'input_skip_bias_sum', TensorProto.FLOAT16, [2, 2, 4]) + + node = onnx.helper.make_node( + 'SkipLayerNormalization', + inputs=['x', 'skip', 'gamma', 'beta', 'bias'], + outputs=['y', 'mean', 'inv_std_var', 'input_skip_bias_sum'], + epsilon=1e-5, + domain="com.microsoft") + + return ([node], [x, skip, gamma, beta, + bias], [y, mean, inv_std_var, input_skip_bias_sum]) + + +@onnx_test() +def skip_layer_normalization_bad_bias_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT16, [2, 2, 4]) + skip = helper.make_tensor_value_info('skip', TensorProto.FLOAT16, + [2, 2, 4]) + gamma = helper.make_tensor_value_info('gamma', TensorProto.FLOAT16, [4]) + beta = helper.make_tensor_value_info('beta', TensorProto.FLOAT16, [4]) + bias = helper.make_tensor_value_info('bias', TensorProto.FLOAT, [4]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT16, [2, 2, 4]) + mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [2, 2, 1]) + inv_std_var = helper.make_tensor_value_info('inv_std_var', + TensorProto.FLOAT, [2, 2, 1]) + input_skip_bias_sum = helper.make_tensor_value_info( + 'input_skip_bias_sum', TensorProto.FLOAT16, [2, 2, 4]) + + node = onnx.helper.make_node( + 'SkipLayerNormalization', + inputs=['x', 'skip', 'gamma', 'beta', 'bias'], + outputs=['y', 'mean', 'inv_std_var', 'input_skip_bias_sum'], + epsilon=1e-5, + domain="com.microsoft") + + return ([node], [x, skip, gamma, beta, + bias], [y, mean, inv_std_var, input_skip_bias_sum]) + + +@onnx_test() +def skip_layer_normalization_invalid_n_args_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT16, [2, 2, 4]) + skip = helper.make_tensor_value_info('skip', TensorProto.FLOAT16, + [2, 2, 4]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT16, [2, 2, 4]) + + node = onnx.helper.make_node('SkipLayerNormalization', + inputs=['x', 'skip'], + outputs=['y'], + epsilon=1e-5, + domain="com.microsoft") + + return ([node], [x, skip], [y]) + + +@onnx_test() +def skip_layer_normalization_invalid_input_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT16, [2, 2, 2, 4]) + skip = helper.make_tensor_value_info('skip', TensorProto.FLOAT16, + [2, 2, 4]) + gamma = helper.make_tensor_value_info('gamma', TensorProto.FLOAT16, [2, 4]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT16, [2, 2, 2, 4]) + + node = onnx.helper.make_node('SkipLayerNormalization', + inputs=['x', 'skip', 'gamma'], + outputs=['y'], + epsilon=1e-5, + domain="com.microsoft") + + return ([node], [x, skip, gamma], [y]) + + @onnx_test() def slice_test(): x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [3, 2]) diff --git a/test/onnx/include/onnx_test_utils.hpp b/test/onnx/include/onnx_test_utils.hpp index e997e615cc5..301bdc743f5 100644 --- a/test/onnx/include/onnx_test_utils.hpp +++ b/test/onnx/include/onnx_test_utils.hpp @@ -202,6 +202,60 @@ make_layer_norm(const std::vector& input_shape, return p; } +inline migraphx::program +make_skip_layer_norm(const std::vector& input_shape, + const std::vector& skip_shape, + const std::vector& gamma_shape, + const std::vector& beta_shape, + const std::vector& bias_shape, + const int axes, + const float eps_value = 1e-5f, + const migraphx::shape::type_t dtype = migraphx::shape::half_type) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", {dtype, input_shape}); + auto skip = mm->add_parameter("skip", {dtype, skip_shape}); + auto scale = mm->add_parameter("gamma", {dtype, gamma_shape}); + + migraphx::instruction_ref beta; + migraphx::instruction_ref bias; + if(beta_shape.size() > 0) + { + beta = mm->add_parameter("beta", {dtype, beta_shape}); + } + + if(bias_shape.size() > 0) + { + bias = mm->add_parameter("bias", {dtype, bias_shape}); + } + + x = add_common_op(*mm, migraphx::make_op("add"), {x, skip}); + if(bias_shape.size() > 0) + x = add_common_op(*mm, migraphx::make_op("add"), {x, bias}); + + auto eps = mm->add_literal(migraphx::literal{migraphx::shape{dtype}, {eps_value}}); + auto mean = mm->add_instruction(migraphx::make_op("reduce_mean", {{"axes", {axes}}}), x); + auto x_sqdiff_mean = add_common_op(*mm, migraphx::make_op("sqdiff"), {x, mean}); + auto var = + mm->add_instruction(migraphx::make_op("reduce_mean", {{"axes", {axes}}}), x_sqdiff_mean); + // mean = mm->add_instruction(migraphx::make_op("convert", {{"target_type", dtype}}), mean); + + auto var_eps = add_common_op(*mm, migraphx::make_op("add"), {var, eps}); + auto rsqrt = mm->add_instruction(migraphx::make_op("rsqrt"), {var_eps}); + + auto x_sub_mean = add_common_op(*mm, migraphx::make_op("sub"), {x, mean}); + auto result = add_common_op(*mm, migraphx::make_op("mul"), {x_sub_mean, rsqrt}); + result = add_common_op(*mm, migraphx::make_op("mul"), {result, scale}); + + if(beta_shape.size() > 0) + { + result = add_common_op(*mm, migraphx::make_op("add"), {result, beta}); + } + + return p; +} + inline migraphx::program make_simplified_layer_norm(const std::vector& input_shape, const std::vector& skip_shape, diff --git a/test/onnx/parse/skip_layer_normalization_beta_bias_test.cpp b/test/onnx/parse/skip_layer_normalization_beta_bias_test.cpp new file mode 100644 index 00000000000..e75ce31916b --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_beta_bias_test.cpp @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ + +#include +#include + +TEST_CASE(skip_layer_normalization_beta_bias_test) +{ + migraphx::program p = make_skip_layer_norm( + {2, 2, 4}, {2, 2, 4}, {4}, {4}, {4}, 2, 1e-5f, migraphx::shape::half_type); + + auto prog = optimize_onnx("skip_layer_normalization_beta_bias_test.onnx"); + EXPECT(p == prog); +} diff --git a/test/onnx/parse/skip_layer_normalization_beta_test.cpp b/test/onnx/parse/skip_layer_normalization_beta_test.cpp new file mode 100644 index 00000000000..b485b103e12 --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_beta_test.cpp @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ + +#include +#include + +TEST_CASE(skip_layer_normalization_beta_test) +{ + migraphx::program p = make_skip_layer_norm( + {2, 2, 4}, {2, 2, 4}, {4}, {4}, {}, 2, 1e-5f, migraphx::shape::half_type); + + auto prog = optimize_onnx("skip_layer_normalization_beta_test.onnx"); + EXPECT(p == prog); +} diff --git a/test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp b/test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp new file mode 100644 index 00000000000..5fbd49e7ef7 --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ + +#include + +TEST_CASE(skip_layer_normalization_invalid_beta_test) +{ + EXPECT(test::throws( + [&] { migraphx::parse_onnx("skip_layer_normalization_invalid_beta_test.onnx"); })); +} diff --git a/test/onnx/parse/skip_layer_normalization_invalid_bias_test.cpp b/test/onnx/parse/skip_layer_normalization_invalid_bias_test.cpp new file mode 100644 index 00000000000..1b78414e9bb --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_invalid_bias_test.cpp @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ + +#include + +TEST_CASE(skip_layer_normalization_invalid_bias_test) +{ + EXPECT(test::throws( + [&] { migraphx::parse_onnx("skip_layer_normalization_invalid_bias_test.onnx"); })); +} diff --git a/test/onnx/parse/skip_layer_normalization_invalid_input_test.cpp b/test/onnx/parse/skip_layer_normalization_invalid_input_test.cpp new file mode 100644 index 00000000000..eb54d758efe --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_invalid_input_test.cpp @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ + +#include + +TEST_CASE(skip_layer_normalization_invalid_input_test) +{ + EXPECT(test::throws( + [&] { migraphx::parse_onnx("skip_layer_normalization_invalid_input_test.onnx"); })); +} diff --git a/test/onnx/parse/skip_layer_normalization_invalid_n_args_test.cpp b/test/onnx/parse/skip_layer_normalization_invalid_n_args_test.cpp new file mode 100644 index 00000000000..241a8147cc4 --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_invalid_n_args_test.cpp @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ + +#include + +TEST_CASE(skip_layer_normalization_invalid_n_args_test) +{ + EXPECT(test::throws( + [&] { migraphx::parse_onnx("skip_layer_normalization_invalid_n_args_test.onnx"); })); +} diff --git a/test/onnx/parse/skip_layer_normalization_test.cpp b/test/onnx/parse/skip_layer_normalization_test.cpp new file mode 100644 index 00000000000..3a57a822e4e --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_test.cpp @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ + +#include +#include + +TEST_CASE(skip_layer_normalization_test) +{ + migraphx::program p = make_skip_layer_norm( + {2, 2, 4}, {2, 2, 4}, {4}, {}, {}, 2, 1e-5f, migraphx::shape::half_type); + + auto prog = optimize_onnx("skip_layer_normalization_test.onnx"); + EXPECT(p == prog); +} diff --git a/test/onnx/skip_layer_normalization_bad_beta_test.onnx b/test/onnx/skip_layer_normalization_bad_beta_test.onnx new file mode 100644 index 00000000000..2766eaa7e92 --- /dev/null +++ b/test/onnx/skip_layer_normalization_bad_beta_test.onnx @@ -0,0 +1,52 @@ + +&skip_layer_normalization_bad_beta_test: +{ +x +skip +gamma +betaymean inv_std_varinput_skip_bias_sum"SkipLayerNormalization* +epsilon'7: com.microsoft&skip_layer_normalization_bad_beta_testZ +x + + + + +Z +skip + + + + +Z +gamma + + + +Z +beta +  + + +b +y + + + + +b +mean + + + +b! + inv_std_var + + + +b) +input_skip_bias_sum + + + + +B \ No newline at end of file diff --git a/test/onnx/skip_layer_normalization_bad_bias_test.onnx b/test/onnx/skip_layer_normalization_bad_bias_test.onnx new file mode 100644 index 00000000000..ad4d405f222 --- /dev/null +++ b/test/onnx/skip_layer_normalization_bad_bias_test.onnx @@ -0,0 +1,57 @@ + +&skip_layer_normalization_bad_bias_test: + +x +skip +gamma +beta +biasymean inv_std_varinput_skip_bias_sum"SkipLayerNormalization* +epsilon'7: com.microsoft&skip_layer_normalization_bad_bias_testZ +x + + + + +Z +skip + + + + +Z +gamma + + + +Z +beta + + + +Z +bias + + +b +y + + + + +b +mean + + + +b! + inv_std_var + + + +b) +input_skip_bias_sum + + + + +B \ No newline at end of file diff --git a/test/onnx/skip_layer_normalization_beta_bias_test.onnx b/test/onnx/skip_layer_normalization_beta_bias_test.onnx new file mode 100644 index 00000000000..5825c23f957 --- /dev/null +++ b/test/onnx/skip_layer_normalization_beta_bias_test.onnx @@ -0,0 +1,58 @@ + +'skip_layer_normalization_beta_bias_test: + +x +skip +gamma +beta +biasymean inv_std_varinput_skip_bias_sum"SkipLayerNormalization* +epsilon'7: com.microsoft'skip_layer_normalization_beta_bias_testZ +x + + + + +Z +skip + + + + +Z +gamma + + + +Z +beta + + + +Z +bias + + + +b +y + + + + +b +mean + + + +b! + inv_std_var + + + +b) +input_skip_bias_sum + + + + +B \ No newline at end of file diff --git a/test/onnx/skip_layer_normalization_beta_test.onnx b/test/onnx/skip_layer_normalization_beta_test.onnx new file mode 100644 index 00000000000..84ebae78ed3 --- /dev/null +++ b/test/onnx/skip_layer_normalization_beta_test.onnx @@ -0,0 +1,52 @@ + +"skip_layer_normalization_beta_test: +{ +x +skip +gamma +betaymean inv_std_varinput_skip_bias_sum"SkipLayerNormalization* +epsilon'7: com.microsoft"skip_layer_normalization_beta_testZ +x + + + + +Z +skip + + + + +Z +gamma + + + +Z +beta + + + +b +y + + + + +b +mean + + + +b! + inv_std_var + + + +b) +input_skip_bias_sum + + + + +B \ No newline at end of file diff --git a/test/onnx/skip_layer_normalization_invalid_input_test.onnx b/test/onnx/skip_layer_normalization_invalid_input_test.onnx new file mode 100644 index 00000000000..f7969294bb0 --- /dev/null +++ b/test/onnx/skip_layer_normalization_invalid_input_test.onnx @@ -0,0 +1,32 @@ + ++skip_layer_normalization_invalid_input_test: +M +x +skip +gammay"SkipLayerNormalization* +epsilon'7: com.microsoft+skip_layer_normalization_invalid_input_testZ +x + + + + + +Z +skip + + + + +Z +gamma +  + + +b +y + + + + + +B \ No newline at end of file diff --git a/test/onnx/skip_layer_normalization_invalid_n_args_test.onnx b/test/onnx/skip_layer_normalization_invalid_n_args_test.onnx new file mode 100644 index 00000000000..b6ae05033fb --- /dev/null +++ b/test/onnx/skip_layer_normalization_invalid_n_args_test.onnx @@ -0,0 +1,24 @@ + +,skip_layer_normalization_invalid_n_args_test: +F +x +skipy"SkipLayerNormalization* +epsilon'7: com.microsoft,skip_layer_normalization_invalid_n_args_testZ +x + + + + +Z +skip + + + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/skip_layer_normalization_test.onnx b/test/onnx/skip_layer_normalization_test.onnx new file mode 100644 index 00000000000..cfaf38fb1f6 --- /dev/null +++ b/test/onnx/skip_layer_normalization_test.onnx @@ -0,0 +1,46 @@ + +skip_layer_normalization_test: +u +x +skip +gammaymean inv_std_varinput_skip_bias_sum"SkipLayerNormalization* +epsilon'7: com.microsoftskip_layer_normalization_testZ +x + + + + +Z +skip + + + + +Z +gamma + + + +b +y + + + + +b +mean + + + +b! + inv_std_var + + + +b) +input_skip_bias_sum + + + + +B \ No newline at end of file diff --git a/test/onnx/verify/skip_layer_normalization.cpp b/test/onnx/verify/skip_layer_normalization.cpp new file mode 100644 index 00000000000..2d6d044b7fb --- /dev/null +++ b/test/onnx/verify/skip_layer_normalization.cpp @@ -0,0 +1,379 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +TEST_CASE(skip_layer_normalization_test) +{ + using migraphx::half; + std::vector x{half{0.8}, + half{-0.5}, + half{0.0}, + half{1.0}, + half{0.5}, + half{0.2}, + half{0.3}, + half{-0.6}, + half{10.0}, + half{-1.0}, + half{0.0}, + half{1.0}, + half{1.2}, + half{3.2}, + half{-4.1}, + half{5.3}}; + std::vector skip{half{1.2}, + half{-1.0}, + half{2.0}, + half{1.0}, + half{1.5}, + half{2.2}, + half{-3.3}, + half{2.6}, + half{1.0}, + half{-10.0}, + half{-1.0}, + half{2.0}, + half{-1.2}, + half{1.6}, + half{-1.1}, + half{1.3}}; + std::vector scale{half{0.1}, half{0.2}, half{4.0}, half{-2.2}}; + + auto p = read_onnx("skip_layer_normalization_test.onnx"); + p.compile(migraphx::make_target("ref")); + + migraphx::shape s_x{migraphx::shape::half_type, {2, 2, 4}}; + migraphx::shape s_s{migraphx::shape::half_type, {4}}; + + migraphx::parameter_map pp; + pp["x"] = migraphx::argument(s_x, x.data()); + pp["skip"] = migraphx::argument(s_x, skip.data()); + pp["gamma"] = migraphx::argument(s_s, scale.data()); + + auto results = p.eval(pp); + auto output = results.at(0); + auto mean = results.at(1); + auto inv_std_var = results.at(2); + auto input_skip_bias_sum = results.at(3); + + std::vector result_vector; + std::vector mean_vector; + std::vector inv_std_var_vector; + std::vector input_skip_bias_sum_vector; + + output.visit([&](auto vals) { result_vector.assign(vals.begin(), vals.end()); }); + mean.visit([&](auto vals) { mean_vector.assign(vals.begin(), vals.end()); }); + inv_std_var.visit([&](auto vals) { inv_std_var_vector.assign(vals.begin(), vals.end()); }); + input_skip_bias_sum.visit( + [&](auto vals) { input_skip_bias_sum_vector.assign(vals.begin(), vals.end()); }); + + std::vector gold = {half{0.05770874}, + half{-0.34619141}, + half{2.30859375}, + half{-1.26953125}, + half{0.05160522}, + half{0.13891602}, + half{-6.91015625}, + half{-1.13476562}, + half{0.13244629}, + half{-0.29028320}, + half{-0.75732422}, + half{-0.69384766}, + half{-0.03375244}, + half{0.14160156}, + half{-5.88671875}, + half{-2.42187500}}; + std::vector gold_mean = { + half{1.12500000}, half{0.84960938}, half{0.50000000}, half{1.54882812}}; + std::vector gold_inv_std_var = { + half{0.65966797}, half{0.44873047}, half{0.12622070}, half{0.21801758}}; + std::vector gold_input_skip_bias_sum = {half{2.00000000}, + half{-1.50000000}, + half{2.00000000}, + half{2.00000000}, + half{2.00000000}, + half{2.39843750}, + half{-3.00000000}, + half{2.00000000}, + half{11.00000000}, + half{-11.00000000}, + half{-1.00000000}, + half{3.00000000}, + half{0.00000000}, + half{4.79687500}, + half{-5.20312500}, + half{6.60156250}}; + + EXPECT(migraphx::verify::verify_rms_range(result_vector, gold)); + EXPECT(migraphx::verify::verify_rms_range(mean_vector, gold_mean)); + EXPECT(migraphx::verify::verify_rms_range(inv_std_var_vector, gold_inv_std_var)); + EXPECT( + migraphx::verify::verify_rms_range(input_skip_bias_sum_vector, gold_input_skip_bias_sum)); +} + +TEST_CASE(skip_layer_normalization_beta_test) +{ + using migraphx::half; + std::vector x{half{0.8}, + half{-0.5}, + half{0.0}, + half{1.0}, + half{0.5}, + half{0.2}, + half{0.3}, + half{-0.6}, + half{10.0}, + half{-1.0}, + half{0.0}, + half{1.0}, + half{1.2}, + half{3.2}, + half{-4.1}, + half{5.3}}; + std::vector skip{half{1.2}, + half{-1.0}, + half{2.0}, + half{1.0}, + half{1.5}, + half{2.2}, + half{-3.3}, + half{2.6}, + half{1.0}, + half{-10.0}, + half{-1.0}, + half{2.0}, + half{-1.2}, + half{1.6}, + half{-1.1}, + half{1.3}}; + std::vector scale{half{0.1}, half{0.2}, half{4.0}, half{-2.2}}; + std::vector beta{half{1.0}, half{1.0}, half{1.0}, half{1.0}}; + + auto p = read_onnx("skip_layer_normalization_beta_test.onnx"); + p.compile(migraphx::make_target("ref")); + + migraphx::shape s_x{migraphx::shape::half_type, {2, 2, 4}}; + migraphx::shape s_s{migraphx::shape::half_type, {4}}; + + migraphx::parameter_map pp; + pp["x"] = migraphx::argument(s_x, x.data()); + pp["skip"] = migraphx::argument(s_x, skip.data()); + pp["gamma"] = migraphx::argument(s_s, scale.data()); + pp["beta"] = migraphx::argument(s_s, beta.data()); + + auto results = p.eval(pp); + auto output = results.at(0); + auto mean = results.at(1); + auto inv_std_var = results.at(2); + auto input_skip_bias_sum = results.at(3); + + std::vector result_vector; + std::vector mean_vector; + std::vector inv_std_var_vector; + std::vector input_skip_bias_sum_vector; + + output.visit([&](auto vals) { result_vector.assign(vals.begin(), vals.end()); }); + mean.visit([&](auto vals) { mean_vector.assign(vals.begin(), vals.end()); }); + inv_std_var.visit([&](auto vals) { inv_std_var_vector.assign(vals.begin(), vals.end()); }); + input_skip_bias_sum.visit( + [&](auto vals) { input_skip_bias_sum_vector.assign(vals.begin(), vals.end()); }); + + std::vector gold = {half{1.05761719}, + half{0.65380859}, + half{3.30859375}, + half{-0.26953125}, + half{1.05175781}, + half{1.13867188}, + half{-5.91015625}, + half{-0.13476562}, + half{1.13281250}, + half{0.70996094}, + half{0.24267578}, + half{0.30615234}, + half{0.96630859}, + half{1.14160156}, + half{-4.88671875}, + half{-1.42187500}}; + std::vector gold_mean = { + half{1.12500000}, half{0.84960938}, half{0.50000000}, half{1.54882812}}; + std::vector gold_inv_std_var = { + half{0.65966797}, half{0.44873047}, half{0.12622070}, half{0.21801758}}; + std::vector gold_input_skip_bias_sum = {half{2.00000000}, + half{-1.50000000}, + half{2.00000000}, + half{2.00000000}, + half{2.00000000}, + half{2.39843750}, + half{-3.00000000}, + half{2.00000000}, + half{11.00000000}, + half{-11.00000000}, + half{-1.00000000}, + half{3.00000000}, + half{0.00000000}, + half{4.79687500}, + half{-5.20312500}, + half{6.60156250}}; + + EXPECT(migraphx::verify::verify_rms_range(result_vector, gold)); + EXPECT(migraphx::verify::verify_rms_range(mean_vector, gold_mean)); + EXPECT(migraphx::verify::verify_rms_range(inv_std_var_vector, gold_inv_std_var)); + EXPECT( + migraphx::verify::verify_rms_range(input_skip_bias_sum_vector, gold_input_skip_bias_sum)); +} + +TEST_CASE(skip_layer_normalization_beta_bias_test) +{ + using migraphx::half; + std::vector x{half{0.8}, + half{-0.5}, + half{0.0}, + half{1.0}, + half{0.5}, + half{0.2}, + half{0.3}, + half{-0.6}, + half{10.0}, + half{-1.0}, + half{0.0}, + half{1.0}, + half{1.2}, + half{3.2}, + half{-4.1}, + half{5.3}}; + std::vector skip{half{1.2}, + half{-1.0}, + half{2.0}, + half{1.0}, + half{1.5}, + half{2.2}, + half{-3.3}, + half{2.6}, + half{1.0}, + half{-10.0}, + half{-1.0}, + half{2.0}, + half{-1.2}, + half{1.6}, + half{-1.1}, + half{1.3}}; + std::vector scale{half{0.1}, half{0.2}, half{4.0}, half{-2.2}}; + std::vector beta{half{1.0}, half{1.0}, half{1.0}, half{1.0}}; + std::vector bias{half{1.0}, half{1.0}, half{1.0}, half{1.0}}; + + auto p = read_onnx("skip_layer_normalization_beta_bias_test.onnx"); + p.compile(migraphx::make_target("ref")); + + migraphx::shape s_x{migraphx::shape::half_type, {2, 2, 4}}; + migraphx::shape s_s{migraphx::shape::half_type, {4}}; + + migraphx::parameter_map pp; + pp["x"] = migraphx::argument(s_x, x.data()); + pp["skip"] = migraphx::argument(s_x, skip.data()); + pp["gamma"] = migraphx::argument(s_s, scale.data()); + pp["beta"] = migraphx::argument(s_s, beta.data()); + pp["bias"] = migraphx::argument(s_s, bias.data()); + + auto results = p.eval(pp); + auto output = results.at(0); + auto mean = results.at(1); + auto inv_std_var = results.at(2); + auto input_skip_bias_sum = results.at(3); + + std::vector result_vector; + std::vector mean_vector; + std::vector inv_std_var_vector; + std::vector input_skip_bias_sum_vector; + + output.visit([&](auto vals) { result_vector.assign(vals.begin(), vals.end()); }); + mean.visit([&](auto vals) { mean_vector.assign(vals.begin(), vals.end()); }); + inv_std_var.visit([&](auto vals) { inv_std_var_vector.assign(vals.begin(), vals.end()); }); + input_skip_bias_sum.visit( + [&](auto vals) { input_skip_bias_sum_vector.assign(vals.begin(), vals.end()); }); + + std::vector gold = {half{1.05761719}, + half{0.65380859}, + half{3.30859375}, + half{-0.26953125}, + half{1.05175781}, + half{1.13867188}, + half{-5.91015625}, + half{-0.13476562}, + half{1.13281250}, + half{0.70996094}, + half{0.24267578}, + half{0.30615234}, + half{0.96630859}, + half{1.14160156}, + half{-4.88671875}, + half{-1.42187500}}; + std::vector gold_mean = { + half{2.12500000}, half{1.84960938}, half{1.50000000}, half{2.54882812}}; + std::vector gold_inv_std_var = { + half{0.65966797}, half{0.44873047}, half{0.12622070}, half{0.21801758}}; + std::vector gold_input_skip_bias_sum = {half{3.00000000}, + half{-0.50000000}, + half{3.00000000}, + half{3.00000000}, + half{3.00000000}, + half{3.39843750}, + half{-2.00000000}, + half{3.00000000}, + half{12.00000000}, + half{-10.00000000}, + half{0.00000000}, + half{4.00000000}, + half{1.00000000}, + half{5.79687500}, + half{-4.20312500}, + half{7.60156250}}; + + // print values of result_vector, mean_vector, inv_std_var_vector, input_skip_bias_sum_vector + std::cout << "result_vector" << std::endl; + for(auto i : result_vector) + std::cout << i << " "; + std::cout << std::endl; + std::cout << "mean_vector" << std::endl; + for(auto i : mean_vector) + std::cout << i << " "; + std::cout << std::endl; + std::cout << "inv_std_var_vector" << std::endl; + for(auto i : inv_std_var_vector) + std::cout << i << " "; + std::cout << std::endl; + std::cout << "input_skip_bias_sum_vector" << std::endl; + for(auto i : input_skip_bias_sum_vector) + std::cout << i << " "; + std::cout << std::endl; + + EXPECT(migraphx::verify::verify_rms_range(result_vector, gold)); + EXPECT(migraphx::verify::verify_rms_range(mean_vector, gold_mean)); + EXPECT(migraphx::verify::verify_rms_range(inv_std_var_vector, gold_inv_std_var)); + EXPECT( + migraphx::verify::verify_rms_range(input_skip_bias_sum_vector, gold_input_skip_bias_sum)); +}