Compute Library
 21.08
QLSTMLayerNormalization.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020-2021 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
26 #include "ArithmeticOperations.h"
31 
32 namespace arm_compute
33 {
34 namespace test
35 {
36 namespace validation
37 {
38 namespace reference
39 {
41 {
42  ARM_COMPUTE_ERROR_ON(src.shape().num_dimensions() > 2);
44 
45  const auto wq_info = weight.quantization_info().uniform();
46  int output_multiplier{};
47  int output_shift{};
48  const auto s = quantization::calculate_quantized_multiplier(wq_info.scale, &output_multiplier, &output_shift);
49  output_shift *= -1;
50 
51  if(!bool(s))
52  {
53  output_multiplier = 0;
54  output_shift = 0;
55  }
56 
57  const uint32_t num_batch = src.shape()[1];
58  const uint32_t num_input = src.shape()[0];
59 
60  for(uint32_t batch_idx = 0; batch_idx < num_batch; ++batch_idx)
61  {
62  int64_t sum{};
63  int64_t sum_sq{};
64 
65  for(uint32_t input_idx = 0; input_idx < num_input; ++input_idx)
66  {
67  const auto index = batch_idx * num_input + input_idx;
68  const auto val = static_cast<int32_t>(src[index]);
69  sum += val;
70  sum_sq += val * val;
71  }
72 
73  const auto temp = static_cast<int64_t>(0x100000) / num_input;
74  const auto mean = sum * 1024 / static_cast<int64_t>(num_input);
75  const auto variance = ((sum_sq * temp) - (mean * mean)) / 0x100000;
76 
77  int32_t stddev_invsqrt_mul{};
78  int32_t stddev_invsqrt_shift{};
79  quantization::get_invsqrt_quantized_multiplier_exp(variance, -1, stddev_invsqrt_mul, stddev_invsqrt_shift);
80 
81  for(uint32_t input_idx = 0; input_idx < num_input; ++input_idx)
82  {
83  const auto index = batch_idx * num_input + input_idx;
84  const auto val = static_cast<int32_t>(src[index]);
85  const auto shifted = (val << 10) - mean;
86  const auto rescaled = quantization::multiply_by_quantized_multiplier(shifted, stddev_invsqrt_mul, stddev_invsqrt_shift);
87  const int64_t weighted = rescaled * weight[input_idx] + bias[input_idx];
88  const auto reverse_shifted = static_cast<int32_t>((weighted + 512) >> 10);
89  auto out_val = quantization::multiply_by_quantized_multiplier(reverse_shifted, output_multiplier, output_shift + 12);
90  out_val = arm_compute::utility::clamp<decltype(out_val), int16_t>(out_val, std::numeric_limits<int16_t>::min());
91  output[index] = static_cast<int16_t>(out_val);
92  }
93  }
94  return output;
95 }
96 } // namespace reference
97 } // namespace validation
98 } // namespace test
99 } // namespace arm_compute
SimpleTensor< int16_t > qlstm_layer_normalization(const SimpleTensor< int16_t > &src, const SimpleTensor< int16_t > &weight, const SimpleTensor< int32_t > &bias)
quantized, symmetric fixed-point 16-bit number
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
TensorShape shape() const override
Shape of the tensor.
Definition: SimpleTensor.h:320
Status calculate_quantized_multiplier(float multiplier, int32_t *quant_multiplier, int32_t *shift, bool ignore_epsilon=false)
Calculate quantized representation of multiplier.
SimpleTensor< float > src
Definition: DFT.cpp:155
Copyright (c) 2017-2021 Arm Limited.
void get_invsqrt_quantized_multiplier_exp(int32_t input, int32_t reverse_shift, int32_t &output_inv_sqrt, int32_t &output_shift)
Compute quantized multiplier and shift for the inverse square root of input.
int32_t multiply_by_quantized_multiplier(int32_t input, int32_t qmul, int32_t shift)
Compute the value multiplied by given quantized multiplier and shift.
Simple tensor object that stores elements in a consecutive chunk of memory.
Definition: SimpleTensor.h:58
QuantizationInfo quantization_info() const override
Quantization info in case of asymmetric quantized type.
Definition: SimpleTensor.h:332