From 88675a9b075b8526143c67771456499e46c29be4 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Sun, 2 Mar 2025 07:06:03 +0000 Subject: [PATCH 01/15] Took simplified version and tweaked a little needs work on input dimensions --- src/onnx/parse_skip_layer_normalization.cpp | 149 ++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/onnx/parse_skip_layer_normalization.cpp diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp new file mode 100644 index 00000000000..185ae1e42ee --- /dev/null +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -0,0 +1,149 @@ +/* + * 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 - 4) + // 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) + // bias (optional) : T + // 1D bias tensor with shape (hidden_size) - not used by ORT + + if(args.size() < 3 or args.size() > 4) + { + MIGRAPHX_THROW("PARSE_SKIPSIMPLIFIEDLAYERNORMALIZATION: invalid input count"); + } + + auto x = args.at(0); + auto skip = args.at(1); + auto gamma = args.at(2); + instruction_ref beta; + instruction_ref bias; + if(args.size() >= 4) + { + beta = args.at(3); + } + if(args.size() == 5) + { + bias = args.at(4); + } + + 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 < 2 or x_rank > 3 or x_rank != skip_rank or gamma_rank != 1) + { + MIGRAPHX_THROW("PARSE_SKIPLAYERNORMALIZATION: invalid input shape"); + } + + x = info.add_common_op("add", x, skip); + // Convert to float before reduce_mean + // Fp16 reduce_mean on GPU causes loss of accuracy + auto float_x = info.add_instruction( + make_op("convert", {{"target_type", migraphx::shape::float_type}}), x); + auto x_sq = info.add_common_op("mul", float_x, float_x); + auto rms = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), x_sq); + rms = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), rms); + auto mean = rms; + epsilon = + (x_dtype == migraphx::shape::half_type and std::abs(epsilon) < 1e-7) ? 1e-7 : epsilon; + auto eps = info.add_literal(migraphx::literal{migraphx::shape{x_dtype}, {epsilon}}); + rms = info.add_common_op("add", rms, eps); + auto rrms = info.add_instruction(make_op("rsqrt"), rms); + auto result = info.add_common_op("mul", x, rrms); + result = info.add_common_op("mul", result, gamma); + if(args.size() == 4) + { + result = info.add_common_op("add", result, bias); + x = info.add_common_op("add", x, bias); + } + + // Outputs (1 - 4) + // output : T + // 3D output tensor with shape (batch_size, sequence_length, hidden_size)Or 2D output tensor + // with shape (token_count, 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, rrms, x}; + } +}; + +} // namespace onnx +} // namespace MIGRAPHX_INLINE_NS +} // namespace migraphx From 270109cc8f7eb7f17a745ea21348ccb4ab57b43d Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Sun, 2 Mar 2025 16:23:48 +0000 Subject: [PATCH 02/15] Adjust parameters to match onnxruntime implimentation --- src/onnx/parse_skip_layer_normalization.cpp | 83 ++++++++++++++------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index 185ae1e42ee..9b016525b77 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -74,7 +74,7 @@ struct parse_skip_simplified_layer_normalization // bias (optional) : T // 1D bias tensor with shape (hidden_size) - not used by ORT - if(args.size() < 3 or args.size() > 4) + if(args.size() < 3 or args.size() > 5) { MIGRAPHX_THROW("PARSE_SKIPSIMPLIFIEDLAYERNORMALIZATION: invalid input count"); } @@ -82,56 +82,89 @@ struct parse_skip_simplified_layer_normalization 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"); + } + instruction_ref beta; instruction_ref bias; + + // Beta always applied at the end result as an affine offset 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 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"); + } } - 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 < 2 or x_rank > 3 or x_rank != skip_rank or gamma_rank != 1) + x = info.add_common_op("add", x, skip); + if(args.size() >= 4) { - MIGRAPHX_THROW("PARSE_SKIPLAYERNORMALIZATION: invalid input shape"); + x = info.add_common_op("add", x, bias); } - x = info.add_common_op("add", x, skip); // Convert to float before reduce_mean // Fp16 reduce_mean on GPU causes loss of accuracy auto float_x = info.add_instruction( make_op("convert", {{"target_type", migraphx::shape::float_type}}), x); - auto x_sq = info.add_common_op("mul", float_x, float_x); - auto rms = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), x_sq); - rms = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), rms); - auto mean = rms; + + // Get the mean of input and squared of the expectation (for variance calc later) + // Var = E( (x - E[x])) ^2) + auto exp_x = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), float_x); + auto pre_var = info.add_common_op("sub", float_x, exp_x); + pre_var = info.add_common_op("mul", pre_var, pre_var); + auto var = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), pre_var); + var = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), var); + auto mean = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), exp_x); + epsilon = (x_dtype == migraphx::shape::half_type and std::abs(epsilon) < 1e-7) ? 1e-7 : epsilon; auto eps = info.add_literal(migraphx::literal{migraphx::shape{x_dtype}, {epsilon}}); - rms = info.add_common_op("add", rms, eps); - auto rrms = info.add_instruction(make_op("rsqrt"), rms); - auto result = info.add_common_op("mul", x, rrms); + 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, exp_x); + result = info.add_common_op("mul", result, r_var); result = info.add_common_op("mul", result, gamma); - if(args.size() == 4) + + if(args.size() == 5) { - result = info.add_common_op("add", result, bias); - x = info.add_common_op("add", x, bias); + result = info.add_common_op("add", result, beta); } // Outputs (1 - 4) // output : T - // 3D output tensor with shape (batch_size, sequence_length, hidden_size)Or 2D output tensor - // with shape (token_count, hidden_size) + // 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 @@ -140,7 +173,7 @@ struct parse_skip_simplified_layer_normalization // exists)with shape (batch_size, sequence_length, hidden_size) or (token_count, // hidden_size). - return {result, mean, rrms, x}; + return {result, mean, r_var, x}; } }; From ecf1fadb715fbc222fc24f113591abbae3392635 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Sun, 2 Mar 2025 19:43:28 +0000 Subject: [PATCH 03/15] Add initial parser tests - leverage existing parser for skipSimplifiedLayerNormalization with added beta input --- test/onnx/gen_onnx.py | 159 ++++++++++++++++++ ..._layer_normalization_invalid_beta_test.cpp | 32 ++++ ..._layer_normalization_invalid_bias_test.cpp | 32 ++++ ...layer_normalization_invalid_input_test.cpp | 32 ++++ ...ayer_normalization_invalid_n_args_test.cpp | 32 ++++ .../parse/skip_layer_normalization_test.cpp | 35 ++++ ...kip_layer_normalization_bad_beta_test.onnx | 52 ++++++ ...kip_layer_normalization_bad_bias_test.onnx | 52 ++++++ ...ip_layer_normalization_beta_bias_test.onnx | 53 ++++++ .../skip_layer_normalization_beta_test.onnx | 52 ++++++ ...ayer_normalization_invalid_input_test.onnx | 32 ++++ ...yer_normalization_invalid_n_args_test.onnx | 24 +++ test/onnx/skip_layer_normalization_test.onnx | 46 +++++ 13 files changed, 633 insertions(+) create mode 100644 test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp create mode 100644 test/onnx/parse/skip_layer_normalization_invalid_bias_test.cpp create mode 100644 test/onnx/parse/skip_layer_normalization_invalid_input_test.cpp create mode 100644 test/onnx/parse/skip_layer_normalization_invalid_n_args_test.cpp create mode 100644 test/onnx/parse/skip_layer_normalization_test.cpp create mode 100644 test/onnx/skip_layer_normalization_bad_beta_test.onnx create mode 100644 test/onnx/skip_layer_normalization_bad_bias_test.onnx create mode 100644 test/onnx/skip_layer_normalization_beta_bias_test.onnx create mode 100644 test/onnx/skip_layer_normalization_beta_test.onnx create mode 100644 test/onnx/skip_layer_normalization_invalid_input_test.onnx create mode 100644 test/onnx/skip_layer_normalization_invalid_n_args_test.onnx create mode 100644 test/onnx/skip_layer_normalization_test.onnx diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index ab94d5e1be8..8fd046c62a5 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, + 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, + 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/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..38d6c080971 --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp @@ -0,0 +1,32 @@ +/* + * 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..a8456d88b33 --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_invalid_bias_test.cpp @@ -0,0 +1,32 @@ +/* + * 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..f3b2f67c34e --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_invalid_input_test.cpp @@ -0,0 +1,32 @@ +/* + * 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..7e272e6a266 --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_invalid_n_args_test.cpp @@ -0,0 +1,32 @@ +/* + * 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..242b5523a03 --- /dev/null +++ b/test/onnx/parse/skip_layer_normalization_test.cpp @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 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_layer_norm( + {2, 2, 4}, {2, 2, 4}, {4}, -1, 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..7f3a893cce3 --- /dev/null +++ b/test/onnx/skip_layer_normalization_bad_bias_test.onnx @@ -0,0 +1,52 @@ + +&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 +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..8047011a92c --- /dev/null +++ b/test/onnx/skip_layer_normalization_beta_bias_test.onnx @@ -0,0 +1,53 @@ + +'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 +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 From 040a9591aa28e852fbb99c77f722f089cba80cf7 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Sun, 2 Mar 2025 19:44:28 +0000 Subject: [PATCH 04/15] Bit of cleanup --- src/onnx/parse_skip_layer_normalization.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index 9b016525b77..2b79088c57b 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -137,12 +137,12 @@ struct parse_skip_simplified_layer_normalization // Get the mean of input and squared of the expectation (for variance calc later) // Var = E( (x - E[x])) ^2) - auto exp_x = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), float_x); - auto pre_var = info.add_common_op("sub", float_x, exp_x); - pre_var = info.add_common_op("mul", pre_var, pre_var); - auto var = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), pre_var); - var = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), var); - auto mean = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), exp_x); + auto exp_x = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), float_x); + auto pr_var = info.add_common_op("sub", float_x, exp_x); + pr_var = info.add_common_op("mul", pr_var, pr_var); + auto var = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), pr_var); + var = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), var); + auto mean = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), exp_x); epsilon = (x_dtype == migraphx::shape::half_type and std::abs(epsilon) < 1e-7) ? 1e-7 : epsilon; @@ -173,6 +173,7 @@ struct parse_skip_simplified_layer_normalization // exists)with shape (batch_size, sequence_length, hidden_size) or (token_count, // hidden_size). + result->debug_print(); return {result, mean, r_var, x}; } }; From 5a55c5717ed2db806ef880c221f967340dce0879 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Mon, 3 Mar 2025 16:59:23 +0000 Subject: [PATCH 05/15] Replace sub/mul with sqdiff --- src/onnx/parse_skip_layer_normalization.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index 2b79088c57b..ccf0d9c0850 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -138,8 +138,7 @@ struct parse_skip_simplified_layer_normalization // Get the mean of input and squared of the expectation (for variance calc later) // Var = E( (x - E[x])) ^2) auto exp_x = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), float_x); - auto pr_var = info.add_common_op("sub", float_x, exp_x); - pr_var = info.add_common_op("mul", pr_var, pr_var); + pr_var = info.add_common_op("sqdiff", {float_x, exp_x}); auto var = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), pr_var); var = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), var); auto mean = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), exp_x); From 9709f302cd4efa3f420ba36bd6850ed687cbe118 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Fri, 7 Mar 2025 00:41:20 +0000 Subject: [PATCH 06/15] Add updated test. --- src/onnx/parse_skip_layer_normalization.cpp | 4 +- test/onnx/include/onnx_test_utils.hpp | 58 +++++++++++++++++++ .../parse/skip_layer_normalization_test.cpp | 4 +- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index ccf0d9c0850..12b6bc3e08c 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -92,7 +92,7 @@ struct parse_skip_simplified_layer_normalization // 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) + if(x_rank != 3 or (x_rank != skip_rank and skip_rank != 2) or gamma_rank != 1) { MIGRAPHX_THROW("PARSE_SKIPLAYERNORMALIZATION: invalid input shape"); } @@ -138,7 +138,7 @@ struct parse_skip_simplified_layer_normalization // Get the mean of input and squared of the expectation (for variance calc later) // Var = E( (x - E[x])) ^2) auto exp_x = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), float_x); - pr_var = info.add_common_op("sqdiff", {float_x, exp_x}); + auto pr_var = info.add_common_op("sqdiff", {float_x, exp_x}); auto var = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), pr_var); var = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), var); auto mean = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), exp_x); diff --git a/test/onnx/include/onnx_test_utils.hpp b/test/onnx/include/onnx_test_utils.hpp index e997e615cc5..23e8edcd33f 100644 --- a/test/onnx/include/onnx_test_utils.hpp +++ b/test/onnx/include/onnx_test_utils.hpp @@ -202,6 +202,64 @@ 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 float_x = mm->add_instruction( + migraphx::make_op("convert", {{"target_type", migraphx::shape::float_type}}), x); + + auto eps = mm->add_literal(migraphx::literal{dtype, {eps_value}}); + auto mean = mm->add_instruction(migraphx::make_op("reduce_mean", {{"axes", {axes}}}), float_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); + var = mm->add_instruction(migraphx::make_op("convert", {{"target_type", dtype}}), var); + 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_test.cpp b/test/onnx/parse/skip_layer_normalization_test.cpp index 242b5523a03..b9a1760034c 100644 --- a/test/onnx/parse/skip_layer_normalization_test.cpp +++ b/test/onnx/parse/skip_layer_normalization_test.cpp @@ -27,8 +27,8 @@ TEST_CASE(skip_layer_normalization_test) { - migraphx::program p = make_layer_norm( - {2, 2, 4}, {2, 2, 4}, {4}, -1, 1e-5f, migraphx::shape::half_type); + migraphx::program p = make_skip_layer_norm( + {2, 2, 4}, {2, 2, 4}, {2}, {}, {}, 2, 1e-5f, migraphx::shape::half_type); auto prog = optimize_onnx("skip_layer_normalization_test.onnx"); EXPECT(p == prog); From 8c4731da7095d694e1a64386a8eb8c08fc85b5bd Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Fri, 7 Mar 2025 01:38:07 +0000 Subject: [PATCH 07/15] Fix parser to ensure inv_std_var is always float and fix standard test to reflect this Required that both mean and variance outputs are float type and not converted. This works as epsilon as well as this attribute is always float as well. Removes a bunch of extra converts when this operator is reduce precision (Float16/bf,etc) --- src/onnx/parse_skip_layer_normalization.cpp | 11 +++++------ test/onnx/include/onnx_test_utils.hpp | 9 +++++---- test/onnx/parse/skip_layer_normalization_test.cpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index 12b6bc3e08c..7a5eb644e65 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -140,19 +140,19 @@ struct parse_skip_simplified_layer_normalization auto exp_x = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), float_x); auto pr_var = info.add_common_op("sqdiff", {float_x, exp_x}); auto var = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), pr_var); - var = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), var); auto mean = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), exp_x); epsilon = (x_dtype == migraphx::shape::half_type and std::abs(epsilon) < 1e-7) ? 1e-7 : epsilon; - auto eps = info.add_literal(migraphx::literal{migraphx::shape{x_dtype}, {epsilon}}); + auto eps = info.add_literal(migraphx::literal{migraphx::shape{migraphx::shape::float_type}, {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); + auto r_var_fp32 = info.add_instruction(make_op("rsqrt"), var_ep); + auto r_var = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), r_var_fp32); // Output is (x - E[x]) * gamma / (sqrt(var(x) - epsilon)) + beta - auto result = info.add_common_op("sub", x, exp_x); + 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); @@ -172,8 +172,7 @@ struct parse_skip_simplified_layer_normalization // exists)with shape (batch_size, sequence_length, hidden_size) or (token_count, // hidden_size). - result->debug_print(); - return {result, mean, r_var, x}; + return {result, exp_x, r_var_fp32, x}; } }; diff --git a/test/onnx/include/onnx_test_utils.hpp b/test/onnx/include/onnx_test_utils.hpp index 23e8edcd33f..b4a138db103 100644 --- a/test/onnx/include/onnx_test_utils.hpp +++ b/test/onnx/include/onnx_test_utils.hpp @@ -237,16 +237,17 @@ make_skip_layer_norm(const std::vector& input_shape, auto float_x = mm->add_instruction( migraphx::make_op("convert", {{"target_type", migraphx::shape::float_type}}), x); - auto eps = mm->add_literal(migraphx::literal{dtype, {eps_value}}); + auto eps = mm->add_literal(migraphx::literal{migraphx::shape::float_type, {eps_value}}); auto mean = mm->add_instruction(migraphx::make_op("reduce_mean", {{"axes", {axes}}}), float_x); - auto x_sqdiff_mean = add_common_op(*mm, migraphx::make_op("sqdiff"), {x, mean}); + auto x_sqdiff_mean = add_common_op(*mm, migraphx::make_op("sqdiff"), {float_x, mean}); auto var = mm->add_instruction(migraphx::make_op("reduce_mean", {{"axes", {axes}}}), x_sqdiff_mean); - var = mm->add_instruction(migraphx::make_op("convert", {{"target_type", dtype}}), var); 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 rsqrt_fp32 = mm->add_instruction(migraphx::make_op("rsqrt"), {var_eps}); + auto rsqrt = mm->add_instruction(migraphx::make_op("convert", {{"target_type", dtype}}), rsqrt_fp32); + 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}); diff --git a/test/onnx/parse/skip_layer_normalization_test.cpp b/test/onnx/parse/skip_layer_normalization_test.cpp index b9a1760034c..fd4f44d7ddc 100644 --- a/test/onnx/parse/skip_layer_normalization_test.cpp +++ b/test/onnx/parse/skip_layer_normalization_test.cpp @@ -28,7 +28,7 @@ TEST_CASE(skip_layer_normalization_test) { migraphx::program p = make_skip_layer_norm( - {2, 2, 4}, {2, 2, 4}, {2}, {}, {}, 2, 1e-5f, migraphx::shape::half_type); + {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); From ba97a85266a806f7b35d413e84f81afa6041ba87 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Fri, 7 Mar 2025 01:55:22 +0000 Subject: [PATCH 08/15] Update tests and handle error found with beta input beta and bias were flipped. Sorted this out and updated parser. captured testing beta path in parser test --- src/onnx/parse_skip_layer_normalization.cpp | 11 +++--- test/onnx/gen_onnx.py | 4 +-- ...kip_layer_normalization_beta_bias_test.cpp | 35 +++++++++++++++++++ .../skip_layer_normalization_beta_test.cpp | 35 +++++++++++++++++++ .../parse/skip_layer_normalization_test.cpp | 2 +- ...kip_layer_normalization_bad_bias_test.onnx | 7 +++- ...ip_layer_normalization_beta_bias_test.onnx | 7 +++- 7 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 test/onnx/parse/skip_layer_normalization_beta_bias_test.cpp create mode 100644 test/onnx/parse/skip_layer_normalization_beta_test.cpp diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index 7a5eb644e65..dbc0bed2e18 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -62,7 +62,7 @@ struct parse_skip_simplified_layer_normalization epsilon = parser.parse_value(info.attributes.at("epsilon")).at(); } - // Inputs (3 - 4) + // 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) @@ -97,10 +97,8 @@ struct parse_skip_simplified_layer_normalization MIGRAPHX_THROW("PARSE_SKIPLAYERNORMALIZATION: invalid input shape"); } - instruction_ref beta; - instruction_ref bias; - // Beta always applied at the end result as an affine offset + instruction_ref beta; if(args.size() >= 4) { beta = args.at(3); @@ -113,6 +111,7 @@ struct parse_skip_simplified_layer_normalization } // Bias is always applied to the input along with any skip input + instruction_ref bias; if(args.size() == 5) { bias = args.at(4); @@ -125,7 +124,7 @@ struct parse_skip_simplified_layer_normalization } x = info.add_common_op("add", x, skip); - if(args.size() >= 4) + if(args.size() >= 5) { x = info.add_common_op("add", x, bias); } @@ -156,7 +155,7 @@ struct parse_skip_simplified_layer_normalization result = info.add_common_op("mul", result, r_var); result = info.add_common_op("mul", result, gamma); - if(args.size() == 5) + if(args.size() >= 4) { result = info.add_common_op("add", result, beta); } diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index 8fd046c62a5..26545711133 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -12753,7 +12753,7 @@ def skip_layer_normalization_beta_bias_test(): epsilon=1e-5, domain="com.microsoft") - return ([node], [x, skip, gamma, + return ([node], [x, skip, gamma, beta, bias], [y, mean, inv_std_var, input_skip_bias_sum]) @@ -12779,7 +12779,7 @@ def skip_layer_normalization_bad_bias_test(): epsilon=1e-5, domain="com.microsoft") - return ([node], [x, skip, gamma, + return ([node], [x, skip, gamma, beta, bias], [y, mean, inv_std_var, input_skip_bias_sum]) 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_test.cpp b/test/onnx/parse/skip_layer_normalization_test.cpp index fd4f44d7ddc..3a57a822e4e 100644 --- a/test/onnx/parse/skip_layer_normalization_test.cpp +++ b/test/onnx/parse/skip_layer_normalization_test.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * 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 diff --git a/test/onnx/skip_layer_normalization_bad_bias_test.onnx b/test/onnx/skip_layer_normalization_bad_bias_test.onnx index 7f3a893cce3..ad4d405f222 100644 --- a/test/onnx/skip_layer_normalization_bad_bias_test.onnx +++ b/test/onnx/skip_layer_normalization_bad_bias_test.onnx @@ -1,5 +1,5 @@  -&skip_layer_normalization_bad_bias_test: +&skip_layer_normalization_bad_bias_test:  x skip @@ -21,6 +21,11 @@ Z gamma + + +Z +beta +   Z diff --git a/test/onnx/skip_layer_normalization_beta_bias_test.onnx b/test/onnx/skip_layer_normalization_beta_bias_test.onnx index 8047011a92c..5825c23f957 100644 --- a/test/onnx/skip_layer_normalization_beta_bias_test.onnx +++ b/test/onnx/skip_layer_normalization_beta_bias_test.onnx @@ -1,5 +1,5 @@  -'skip_layer_normalization_beta_bias_test: +'skip_layer_normalization_beta_bias_test:  x skip @@ -21,6 +21,11 @@ Z gamma + + +Z +beta +   Z From 18b5419be3d65e8b8bd9f8e2534856ad9e50edd7 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous Date: Fri, 7 Mar 2025 03:09:13 +0000 Subject: [PATCH 09/15] Add verify for skip_layer_normalization - WIP Needs to have values checked. Currently working out data. Just grabbed the skip_simplied_layernorm portion and reused this while modying tests to add in beta and bias values We should be performing the following operation to verify data via numpy https://pytorch.org/docs/stable/generated/torch.nn.LayerNorm.html --- test/onnx/verify/skip_layer_normalization.cpp | 357 ++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 test/onnx/verify/skip_layer_normalization.cpp diff --git a/test/onnx/verify/skip_layer_normalization.cpp b/test/onnx/verify/skip_layer_normalization.cpp new file mode 100644 index 00000000000..e9d443b0061 --- /dev/null +++ b/test/onnx/verify/skip_layer_normalization.cpp @@ -0,0 +1,357 @@ +/* + * 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{1.02076491}, + half{0.89526127}, + half{1.83059639}, + half{0.54317199}, + half{1.02076491}, + half{1.05824622}, + half{-2.34850493}, + half{0.54317199}, + half{1.20882447}, + half{0.49824664}, + half{-0.6768644}, + half{-0.08347084}, + half{0.9789739}, + half{1.15854466}, + half{-4.1873095}, + half{-1.57145328}}; + std::vector gold_mean{half{1.125}, half{0.85}, half{0.5}, half{1.55}}; + std::vector gold_inv_std_var{half{0.65982744}, half{0.44867371}, half{0.12623887}, half{0.21817888}}; + std::vector gold_input_skip_bias_sum = {half{2.0}, + half{-1.5}, + half{2.0}, + half{2.0}, + half{2.0}, + half{2.3984375}, + half{-3.0}, + half{2.0}, + half{11.0}, + half{-11.0}, + half{-1.0}, + half{3.0}, + half{0.0}, + half{4.796875}, + half{-5.203125}, + half{6.6015625}}; + + 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.10596}, + half{0.8411}, + half{5.24}, + half{-1.33}, + half{1.0838}, + half{1.2012}, + half{-4.03}, + half{-0.844}, + half{1.1385}, + half{0.723}, + half{0.496}, + half{0.169}, + half{1.0}, + half{1.1984}, + half{-3.3}, + half{-2.0}}; + + std::vector gold_mean{half{3.5625}, half{5.6875}, half{63.0}, half{23.421875}}; + std::vector gold_inv_std_var{half{0.5298}, half{0.4194}, half{0.1260}, half{0.2067}}; + std::vector gold_input_skip_bias_sum = {half{3.0}, + half{-0.5}, + half{3.0}, + half{3.0}, + half{3.0}, + half{3.3984375}, + half{-2.0}, + half{3.0}, + half{12.0}, + half{-10.0}, + half{0.0}, + half{4.0}, + half{1.0}, + half{5.796875}, + half{-4.203125}, + half{7.6015625}}; + + 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_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.10596}, + half{0.8411}, + half{5.24}, + half{-1.33}, + half{1.0838}, + half{1.2012}, + half{-4.03}, + half{-0.844}, + half{1.1385}, + half{0.723}, + half{0.496}, + half{0.169}, + half{1.0}, + half{1.1984}, + half{-3.3}, + half{-2.0}}; + + std::vector gold_mean{half{3.5625}, half{5.6875}, half{63.0}, half{23.421875}}; + std::vector gold_inv_std_var{half{0.5298}, half{0.4194}, half{0.1260}, half{0.2067}}; + std::vector gold_input_skip_bias_sum = {half{3.0}, + half{-0.5}, + half{3.0}, + half{3.0}, + half{3.0}, + half{3.3984375}, + half{-2.0}, + half{3.0}, + half{12.0}, + half{-10.0}, + half{0.0}, + half{4.0}, + half{1.0}, + half{5.796875}, + half{-4.203125}, + half{7.6015625}}; + + 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)); +} From 84de2c63de2aa787276560d92af546fefdf0995f Mon Sep 17 00:00:00 2001 From: Ahsan Saghir Date: Wed, 26 Mar 2025 08:05:42 -0700 Subject: [PATCH 10/15] Update comments to add missing beta input parameter --- src/onnx/parse_skip_layer_normalization.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index dbc0bed2e18..e572b74a9e2 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -71,6 +71,8 @@ struct parse_skip_simplified_layer_normalization // 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 From c2baa5d28d4ae76bc454987ffcb9d8eae322cd17 Mon Sep 17 00:00:00 2001 From: Ahsan Saghir Date: Wed, 26 Mar 2025 08:40:18 -0700 Subject: [PATCH 11/15] Make changes to leverage reduce_rewrite optimization --- src/onnx/parse_skip_layer_normalization.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index e572b74a9e2..accac4cd1c9 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -131,26 +131,20 @@ struct parse_skip_simplified_layer_normalization x = info.add_common_op("add", x, bias); } - // Convert to float before reduce_mean - // Fp16 reduce_mean on GPU causes loss of accuracy - auto float_x = info.add_instruction( - make_op("convert", {{"target_type", migraphx::shape::float_type}}), x); - // Get the mean of input and squared of the expectation (for variance calc later) // Var = E( (x - E[x])) ^2) - auto exp_x = info.add_instruction(make_op("reduce_mean", {{"axes", {axis}}}), float_x); - auto pr_var = info.add_common_op("sqdiff", {float_x, exp_x}); + 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); - auto mean = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), exp_x); epsilon = - (x_dtype == migraphx::shape::half_type and std::abs(epsilon) < 1e-7) ? 1e-7 : epsilon; - auto eps = info.add_literal(migraphx::literal{migraphx::shape{migraphx::shape::float_type}, {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_fp32 = info.add_instruction(make_op("rsqrt"), var_ep); - auto r_var = info.add_instruction(make_op("convert", {{"target_type", x_dtype}}), r_var_fp32); + 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); @@ -173,7 +167,7 @@ struct parse_skip_simplified_layer_normalization // exists)with shape (batch_size, sequence_length, hidden_size) or (token_count, // hidden_size). - return {result, exp_x, r_var_fp32, x}; + return {result, mean, r_var, x}; } }; From f10379425c7789dff18232c184afaa8aff0884a2 Mon Sep 17 00:00:00 2001 From: Ahsan Saghir Date: Wed, 26 Mar 2025 11:43:19 -0700 Subject: [PATCH 12/15] Use correct onnx file for skip_layer_normalization_beta_bias_test --- test/onnx/verify/skip_layer_normalization.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/onnx/verify/skip_layer_normalization.cpp b/test/onnx/verify/skip_layer_normalization.cpp index e9d443b0061..220d0eb7c12 100644 --- a/test/onnx/verify/skip_layer_normalization.cpp +++ b/test/onnx/verify/skip_layer_normalization.cpp @@ -283,7 +283,7 @@ TEST_CASE(skip_layer_normalization_beta_bias_test) 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_test.onnx"); + 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}}; From 25f2b8f2227605d20903216fe329af5929a25d7b Mon Sep 17 00:00:00 2001 From: Ahsan Saghir Date: Wed, 26 Mar 2025 11:46:42 -0700 Subject: [PATCH 13/15] Update gold values in tests by generated values --- test/onnx/verify/skip_layer_normalization.cpp | 228 ++++++++++-------- 1 file changed, 125 insertions(+), 103 deletions(-) diff --git a/test/onnx/verify/skip_layer_normalization.cpp b/test/onnx/verify/skip_layer_normalization.cpp index 220d0eb7c12..2d6d044b7fb 100644 --- a/test/onnx/verify/skip_layer_normalization.cpp +++ b/test/onnx/verify/skip_layer_normalization.cpp @@ -92,40 +92,42 @@ TEST_CASE(skip_layer_normalization_test) input_skip_bias_sum.visit( [&](auto vals) { input_skip_bias_sum_vector.assign(vals.begin(), vals.end()); }); - std::vector gold = {half{1.02076491}, - half{0.89526127}, - half{1.83059639}, - half{0.54317199}, - half{1.02076491}, - half{1.05824622}, - half{-2.34850493}, - half{0.54317199}, - half{1.20882447}, - half{0.49824664}, - half{-0.6768644}, - half{-0.08347084}, - half{0.9789739}, - half{1.15854466}, - half{-4.1873095}, - half{-1.57145328}}; - std::vector gold_mean{half{1.125}, half{0.85}, half{0.5}, half{1.55}}; - std::vector gold_inv_std_var{half{0.65982744}, half{0.44867371}, half{0.12623887}, half{0.21817888}}; - std::vector gold_input_skip_bias_sum = {half{2.0}, - half{-1.5}, - half{2.0}, - half{2.0}, - half{2.0}, - half{2.3984375}, - half{-3.0}, - half{2.0}, - half{11.0}, - half{-11.0}, - half{-1.0}, - half{3.0}, - half{0.0}, - half{4.796875}, - half{-5.203125}, - half{6.6015625}}; + 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)); @@ -201,41 +203,42 @@ TEST_CASE(skip_layer_normalization_beta_test) input_skip_bias_sum.visit( [&](auto vals) { input_skip_bias_sum_vector.assign(vals.begin(), vals.end()); }); - std::vector gold = {half{1.10596}, - half{0.8411}, - half{5.24}, - half{-1.33}, - half{1.0838}, - half{1.2012}, - half{-4.03}, - half{-0.844}, - half{1.1385}, - half{0.723}, - half{0.496}, - half{0.169}, - half{1.0}, - half{1.1984}, - half{-3.3}, - half{-2.0}}; - - std::vector gold_mean{half{3.5625}, half{5.6875}, half{63.0}, half{23.421875}}; - std::vector gold_inv_std_var{half{0.5298}, half{0.4194}, half{0.1260}, half{0.2067}}; - std::vector gold_input_skip_bias_sum = {half{3.0}, - half{-0.5}, - half{3.0}, - half{3.0}, - half{3.0}, - half{3.3984375}, - half{-2.0}, - half{3.0}, - half{12.0}, - half{-10.0}, - half{0.0}, - half{4.0}, - half{1.0}, - half{5.796875}, - half{-4.203125}, - half{7.6015625}}; + 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)); @@ -313,41 +316,60 @@ TEST_CASE(skip_layer_normalization_beta_bias_test) input_skip_bias_sum.visit( [&](auto vals) { input_skip_bias_sum_vector.assign(vals.begin(), vals.end()); }); - std::vector gold = {half{1.10596}, - half{0.8411}, - half{5.24}, - half{-1.33}, - half{1.0838}, - half{1.2012}, - half{-4.03}, - half{-0.844}, - half{1.1385}, - half{0.723}, - half{0.496}, - half{0.169}, - half{1.0}, - half{1.1984}, - half{-3.3}, - half{-2.0}}; + 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}}; - std::vector gold_mean{half{3.5625}, half{5.6875}, half{63.0}, half{23.421875}}; - std::vector gold_inv_std_var{half{0.5298}, half{0.4194}, half{0.1260}, half{0.2067}}; - std::vector gold_input_skip_bias_sum = {half{3.0}, - half{-0.5}, - half{3.0}, - half{3.0}, - half{3.0}, - half{3.3984375}, - half{-2.0}, - half{3.0}, - half{12.0}, - half{-10.0}, - half{0.0}, - half{4.0}, - half{1.0}, - half{5.796875}, - half{-4.203125}, - half{7.6015625}}; + // 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)); From b90c76b77784ac82ccfac50dd78643ea30668168 Mon Sep 17 00:00:00 2001 From: Ahsan Saghir Date: Thu, 27 Mar 2025 08:13:11 -0700 Subject: [PATCH 14/15] Update make_skip_layer_norm for onnx parse tests --- test/onnx/include/onnx_test_utils.hpp | 29 +++++++++++---------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/test/onnx/include/onnx_test_utils.hpp b/test/onnx/include/onnx_test_utils.hpp index b4a138db103..301bdc743f5 100644 --- a/test/onnx/include/onnx_test_utils.hpp +++ b/test/onnx/include/onnx_test_utils.hpp @@ -215,7 +215,7 @@ make_skip_layer_norm(const std::vector& input_shape, 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 skip = mm->add_parameter("skip", {dtype, skip_shape}); auto scale = mm->add_parameter("gamma", {dtype, gamma_shape}); migraphx::instruction_ref beta; @@ -234,27 +234,22 @@ make_skip_layer_norm(const std::vector& input_shape, if(bias_shape.size() > 0) x = add_common_op(*mm, migraphx::make_op("add"), {x, bias}); - auto float_x = mm->add_instruction( - migraphx::make_op("convert", {{"target_type", migraphx::shape::float_type}}), x); - - auto eps = mm->add_literal(migraphx::literal{migraphx::shape::float_type, {eps_value}}); - auto mean = mm->add_instruction(migraphx::make_op("reduce_mean", {{"axes", {axes}}}), float_x); - auto x_sqdiff_mean = add_common_op(*mm, migraphx::make_op("sqdiff"), {float_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 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_fp32 = mm->add_instruction(migraphx::make_op("rsqrt"), {var_eps}); - auto rsqrt = mm->add_instruction(migraphx::make_op("convert", {{"target_type", dtype}}), rsqrt_fp32); + 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}); + 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}); } From c4eaa4f8cc23ece838873d601e8e5f1745a4a6f9 Mon Sep 17 00:00:00 2001 From: Ahsan Saghir Date: Thu, 27 Mar 2025 08:34:55 -0700 Subject: [PATCH 15/15] Fix formatting --- src/onnx/parse_skip_layer_normalization.cpp | 13 ++++++------- .../skip_layer_normalization_invalid_beta_test.cpp | 5 ++--- .../skip_layer_normalization_invalid_bias_test.cpp | 5 ++--- .../skip_layer_normalization_invalid_input_test.cpp | 5 ++--- ...skip_layer_normalization_invalid_n_args_test.cpp | 5 ++--- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/onnx/parse_skip_layer_normalization.cpp b/src/onnx/parse_skip_layer_normalization.cpp index accac4cd1c9..bd6d0d63366 100644 --- a/src/onnx/parse_skip_layer_normalization.cpp +++ b/src/onnx/parse_skip_layer_normalization.cpp @@ -85,7 +85,6 @@ struct parse_skip_simplified_layer_normalization 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(); @@ -103,7 +102,7 @@ struct parse_skip_simplified_layer_normalization instruction_ref beta; if(args.size() >= 4) { - beta = args.at(3); + 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) @@ -116,7 +115,7 @@ struct parse_skip_simplified_layer_normalization instruction_ref bias; if(args.size() == 5) { - bias = args.at(4); + 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) @@ -133,18 +132,18 @@ struct parse_skip_simplified_layer_normalization // 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 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}}); + (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); + 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); diff --git a/test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp b/test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp index 38d6c080971..5fbd49e7ef7 100644 --- a/test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp +++ b/test/onnx/parse/skip_layer_normalization_invalid_beta_test.cpp @@ -26,7 +26,6 @@ TEST_CASE(skip_layer_normalization_invalid_beta_test) { - EXPECT(test::throws([&] { - migraphx::parse_onnx("skip_layer_normalization_invalid_beta_test.onnx"); - })); + 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 index a8456d88b33..1b78414e9bb 100644 --- a/test/onnx/parse/skip_layer_normalization_invalid_bias_test.cpp +++ b/test/onnx/parse/skip_layer_normalization_invalid_bias_test.cpp @@ -26,7 +26,6 @@ TEST_CASE(skip_layer_normalization_invalid_bias_test) { - EXPECT(test::throws([&] { - migraphx::parse_onnx("skip_layer_normalization_invalid_bias_test.onnx"); - })); + 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 index f3b2f67c34e..eb54d758efe 100644 --- a/test/onnx/parse/skip_layer_normalization_invalid_input_test.cpp +++ b/test/onnx/parse/skip_layer_normalization_invalid_input_test.cpp @@ -26,7 +26,6 @@ TEST_CASE(skip_layer_normalization_invalid_input_test) { - EXPECT(test::throws([&] { - migraphx::parse_onnx("skip_layer_normalization_invalid_input_test.onnx"); - })); + 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 index 7e272e6a266..241a8147cc4 100644 --- a/test/onnx/parse/skip_layer_normalization_invalid_n_args_test.cpp +++ b/test/onnx/parse/skip_layer_normalization_invalid_n_args_test.cpp @@ -26,7 +26,6 @@ TEST_CASE(skip_layer_normalization_invalid_n_args_test) { - EXPECT(test::throws([&] { - migraphx::parse_onnx("skip_layer_normalization_invalid_n_args_test.onnx"); - })); + EXPECT(test::throws( + [&] { migraphx::parse_onnx("skip_layer_normalization_invalid_n_args_test.onnx"); })); }