COMPMID-3314: Enable OpenMP in the reference tests
authorMichalis Spyrou <michalis.spyrou@arm.com>
Wed, 8 Apr 2020 13:10:15 +0000 (14:10 +0100)
committerMichalis Spyrou <michalis.spyrou@arm.com>
Fri, 17 Apr 2020 14:20:01 +0000 (14:20 +0000)
Change-Id: I05b5fedb998317144e0dd13a6377a97207b27f46
Signed-off-by: Michalis Spyrou <michalis.spyrou@arm.com>
Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/3024
Tested-by: Arm Jenkins <bsgcomp@arm.com>
Reviewed-by: Michele Di Giorgio <michele.digiorgio@arm.com>
Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>

51 files changed:
tests/SConscript
tests/validation/Helpers.cpp
tests/validation/reference/AbsoluteDifference.cpp
tests/validation/reference/Accumulate.cpp
tests/validation/reference/ActivationLayer.cpp
tests/validation/reference/ArithmeticDivision.cpp
tests/validation/reference/ArithmeticOperations.cpp
tests/validation/reference/BatchNormalizationLayer.cpp
tests/validation/reference/BitwiseAnd.cpp
tests/validation/reference/BitwiseNot.cpp
tests/validation/reference/BitwiseOr.cpp
tests/validation/reference/BitwiseXor.cpp
tests/validation/reference/BoundingBoxTransform.cpp
tests/validation/reference/Box3x3.cpp
tests/validation/reference/ChannelCombine.cpp
tests/validation/reference/ChannelExtract.cpp
tests/validation/reference/ChannelShuffle.cpp
tests/validation/reference/Col2Im.cpp
tests/validation/reference/Comparisons.cpp
tests/validation/reference/ComputeAllAnchors.cpp
tests/validation/reference/ConvertFullyConnectedWeights.cpp
tests/validation/reference/Convolution.cpp
tests/validation/reference/ConvolutionLayer.cpp
tests/validation/reference/DFT.cpp
tests/validation/reference/DeconvolutionLayer.cpp
tests/validation/reference/DepthConcatenateLayer.cpp
tests/validation/reference/DepthConvertLayer.cpp
tests/validation/reference/DepthToSpaceLayer.cpp
tests/validation/reference/DequantizationLayer.cpp
tests/validation/reference/Derivative.cpp
tests/validation/reference/Dilate.cpp
tests/validation/reference/ElementWiseUnary.cpp
tests/validation/reference/EqualizeHistogram.cpp
tests/validation/reference/Erode.cpp
tests/validation/reference/Floor.cpp
tests/validation/reference/FullyConnectedLayer.cpp
tests/validation/reference/FuseBatchNormalization.cpp
tests/validation/reference/GEMM.cpp
tests/validation/reference/GEMMLowp.cpp
tests/validation/reference/GEMMReshapeLHSMatrix.cpp
tests/validation/reference/GEMMReshapeRHSMatrix.cpp
tests/validation/reference/Gaussian3x3.cpp
tests/validation/reference/Gaussian5x5.cpp
tests/validation/reference/Im2Col.cpp
tests/validation/reference/InstanceNormalizationLayer.cpp
tests/validation/reference/QuantizationLayer.cpp
tests/validation/reference/ReorgLayer.cpp
tests/validation/reference/Reverse.cpp
tests/validation/reference/SoftmaxLayer.cpp
tests/validation/reference/Winograd.cpp
tests/validation/reference/YOLOLayer.cpp

index 5c95c551f4bb2ce8cc1da831cbe7c6d6154d862f..26d422c10be927c0b992647a9590d2e4bd14b416 100644 (file)
@@ -30,6 +30,7 @@ Import('install_bin')
 variables = [
     BoolVariable("benchmark_examples", "Build benchmark examples programs", True),
     BoolVariable("validate_examples", "Build validate examples programs", True),
+    BoolVariable("reference_openmp", "Build reference validation with openmp", True),
     #FIXME Switch the following two options to False before releasing
     BoolVariable("validation_tests", "Build validation test programs", True),
     BoolVariable("benchmark_tests", "Build benchmark test programs", True),
@@ -170,8 +171,12 @@ bm_link_flags = ['-fstack-protector-strong']
 if test_env['linker_script']:
     bm_link_flags += ['-Wl,--build-id=none', '-T', env['linker_script']]
 
+if test_env['reference_openmp'] and env['os'] != 'bare_metal':
+   test_env['CXXFLAGS'].append('-fopenmp')
+   test_env['LINKFLAGS'].append('-fopenmp')
+
 if test_env['validation_tests']:
-    arm_compute_validation_framework = env.StaticLibrary('arm_compute_validation_framework', Glob('validation/reference/*.cpp') + Glob('validation/*.cpp'), LIBS= [ arm_compute_test_framework, arm_compute_core_a])
+    arm_compute_validation_framework = env.StaticLibrary('arm_compute_validation_framework', Glob('validation/reference/*.cpp') + Glob('validation/*.cpp'), LINKFLAGS=test_env['LINKFLAGS'], CXXFLAGS=test_env['CXXFLAGS'], LIBS= [ arm_compute_test_framework, arm_compute_core_a])
     Depends(arm_compute_validation_framework , arm_compute_test_framework)
     Depends(arm_compute_validation_framework , arm_compute_core_a)
 
index 093271244e7a15a36589a0edfd104b471404bf09..6e93cd0638f77f3e98ffc97a9e2ba16bce0bd7f8 100644 (file)
@@ -113,7 +113,9 @@ SimpleTensor<float> convert_from_asymmetric(const SimpleTensor<uint8_t> &src)
 {
     const UniformQuantizationInfo &quantization_info = src.quantization_info().uniform();
     SimpleTensor<float>            dst{ src.shape(), DataType::F32, 1, QuantizationInfo(), src.data_layout() };
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = dequantize_qasymm8(src[i], quantization_info);
@@ -127,6 +129,9 @@ SimpleTensor<float> convert_from_asymmetric(const SimpleTensor<int8_t> &src)
     const UniformQuantizationInfo &quantization_info = src.quantization_info().uniform();
     SimpleTensor<float>            dst{ src.shape(), DataType::F32, 1, QuantizationInfo(), src.data_layout() };
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = dequantize_qasymm8_signed(src[i], quantization_info);
@@ -140,6 +145,9 @@ SimpleTensor<float> convert_from_asymmetric(const SimpleTensor<uint16_t> &src)
     const UniformQuantizationInfo &quantization_info = src.quantization_info().uniform();
     SimpleTensor<float>            dst{ src.shape(), DataType::F32, 1, QuantizationInfo(), src.data_layout() };
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = dequantize_qasymm16(src[i], quantization_info);
@@ -153,6 +161,9 @@ SimpleTensor<uint8_t> convert_to_asymmetric(const SimpleTensor<float> &src, cons
     SimpleTensor<uint8_t>          dst{ src.shape(), DataType::QASYMM8, 1, quantization_info };
     const UniformQuantizationInfo &qinfo = quantization_info.uniform();
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = quantize_qasymm8(src[i], qinfo);
@@ -166,6 +177,9 @@ SimpleTensor<int8_t> convert_to_asymmetric(const SimpleTensor<float> &src, const
     SimpleTensor<int8_t>           dst{ src.shape(), DataType::QASYMM8_SIGNED, 1, quantization_info };
     const UniformQuantizationInfo &qinfo = quantization_info.uniform();
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = quantize_qasymm8_signed(src[i], qinfo);
@@ -179,6 +193,9 @@ SimpleTensor<uint16_t> convert_to_asymmetric(const SimpleTensor<float> &src, con
     SimpleTensor<uint16_t>         dst{ src.shape(), DataType::QASYMM16, 1, quantization_info };
     const UniformQuantizationInfo &qinfo = quantization_info.uniform();
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = quantize_qasymm16(src[i], qinfo);
@@ -192,6 +209,9 @@ SimpleTensor<int16_t> convert_to_symmetric(const SimpleTensor<float> &src, const
     SimpleTensor<int16_t>          dst{ src.shape(), DataType::QSYMM16, 1, quantization_info };
     const UniformQuantizationInfo &qinfo = quantization_info.uniform();
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = quantize_qsymm16(src[i], qinfo);
@@ -205,6 +225,9 @@ SimpleTensor<float> convert_from_symmetric(const SimpleTensor<int16_t> &src)
     const UniformQuantizationInfo &quantization_info = src.quantization_info().uniform();
     SimpleTensor<float>            dst{ src.shape(), DataType::F32, 1, QuantizationInfo(), src.data_layout() };
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = dequantize_qsymm16(src[i], quantization_info);
@@ -223,6 +246,9 @@ void matrix_multiply(const SimpleTensor<T> &a, const SimpleTensor<T> &b, SimpleT
     const int N = b.shape()[0]; // Cols
     const int K = b.shape()[1];
 
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(2)
+#endif /* _OPENMP */
     for(int y = 0; y < M; ++y)
     {
         for(int x = 0; x < N; ++x)
@@ -246,6 +272,9 @@ void transpose_matrix(const SimpleTensor<T> &in, SimpleTensor<T> &out)
     const int width  = in.shape()[0];
     const int height = in.shape()[1];
 
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(2)
+#endif /* _OPENMP */
     for(int y = 0; y < height; ++y)
     {
         for(int x = 0; x < width; ++x)
index f9fce5b42a3836e2f4dcad82ae7a3bdc3e98ba04..ea7685bc9eaf9ad476d5e1587244434e36fb1b6f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -40,7 +40,9 @@ SimpleTensor<T> absolute_difference(const SimpleTensor<T> &src1, const SimpleTen
     SimpleTensor<T> result(src1.shape(), dst_data_type);
 
     using intermediate_type = typename common_promoted_signed_type<T>::intermediate_type;
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src1.num_elements(); ++i)
     {
         intermediate_type val = std::abs(static_cast<intermediate_type>(src1[i]) - static_cast<intermediate_type>(src2[i]));
index 7f34be96635a774eff1c9bf4f31dc7b1ff234a24..2758577ef9bb3b518bc7032d316a4515eee5d49c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -42,7 +42,9 @@ SimpleTensor<T2> accumulate(const SimpleTensor<T1> &src, DataType output_data_ty
     library->fill_tensor_uniform(dst, 1, static_cast<T2>(0), static_cast<T2>(std::numeric_limits<T1>::max()));
 
     using intermediate_type = typename common_promoted_signed_type<T1, T2>::intermediate_type;
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         intermediate_type val = static_cast<intermediate_type>(src[i]) + static_cast<intermediate_type>(dst[i]);
@@ -62,7 +64,9 @@ SimpleTensor<T2> accumulate_weighted(const SimpleTensor<T1> &src, float alpha, D
     library->fill_tensor_uniform(dst, 1, static_cast<T2>(0), static_cast<T2>(std::numeric_limits<T1>::max()));
 
     using intermediate_type = typename common_promoted_signed_type<T1, T2>::intermediate_type;
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         double val = (1. - static_cast<double>(alpha)) * static_cast<intermediate_type>(dst[i]) + static_cast<double>(alpha) * static_cast<intermediate_type>(src[i]);
@@ -83,7 +87,9 @@ SimpleTensor<T2> accumulate_squared(const SimpleTensor<T1> &src, uint32_t shift,
 
     using intermediate_type = typename common_promoted_signed_type<T1, T2>::intermediate_type;
     intermediate_type denom = 1 << shift;
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         intermediate_type val = static_cast<intermediate_type>(dst[i]) + (static_cast<intermediate_type>(src[i]) * static_cast<intermediate_type>(src[i]) / denom);
index 4aa0f880dac7aade784dbd666fb902743acb38ba..4aeefaaa79301c61e64d1611ac59722dfdfa9e63 100644 (file)
@@ -45,7 +45,9 @@ SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo
     // Compute reference
     const T a(info.a());
     const T b(info.b());
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = activate_float<T>(src[i], a, b, info.activation());
@@ -86,7 +88,6 @@ SimpleTensor<int16_t> activation_layer<int16_t>(const SimpleTensor<int16_t> &src
     SimpleTensor<int16_t> dst     = convert_to_symmetric<int16_t>(dst_tmp, dst_qinfo);
     return dst;
 }
-
 template SimpleTensor<int32_t> activation_layer(const SimpleTensor<int32_t> &src, ActivationLayerInfo info, const QuantizationInfo &oq_info);
 template SimpleTensor<float> activation_layer(const SimpleTensor<float> &src, ActivationLayerInfo info, const QuantizationInfo &oq_info);
 template SimpleTensor<half> activation_layer(const SimpleTensor<half> &src, ActivationLayerInfo info, const QuantizationInfo &oq_info);
index 0ced43940420625e55449146ec686d0bfd4a857a..f86ee5e5997ed1925f1dab8e4af51b6c37cb9466 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -49,13 +49,16 @@ struct BroadcastUnroll
         id_src1.set(dim - 1, 0);
         id_src2.set(dim - 1, 0);
         id_dst.set(dim - 1, 0);
-
-        for(size_t i = 0; i < dst.shape()[dim - 1]; ++i, ++id_dst[dim - 1])
+#if defined(_OPENMP)
+        #pragma omp parallel for
+#endif /* _OPENMP */
+        for(size_t i = 0; i < dst.shape()[dim - 1]; ++i)
         {
             BroadcastUnroll < dim - 1 >::unroll(src1, src2, dst, id_src1, id_src2, id_dst);
 
             id_src1[dim - 1] += !src1_is_broadcast;
             id_src2[dim - 1] += !src2_is_broadcast;
+            ++id_dst[dim - 1];
         }
     }
 };
index d86833fefa47eede3e75f642b598f8e73cffec0c..fd32f45cfaaf856f8947c9f7a7ef60f6d335b7af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -62,13 +62,16 @@ struct BroadcastUnroll
         id_src1.set(dim - 1, 0);
         id_src2.set(dim - 1, 0);
         id_dst.set(dim - 1, 0);
-
-        for(size_t i = 0; i < dst.shape()[dim - 1]; ++i, ++id_dst[dim - 1])
+#if defined(_OPENMP)
+        #pragma omp parallel for
+#endif /* _OPENMP */
+        for(size_t i = 0; i < dst.shape()[dim - 1]; ++i)
         {
             BroadcastUnroll < dim - 1 >::unroll(op, src1, src2, dst, convert_policy, id_src1, id_src2, id_dst);
 
             id_src1[dim - 1] += !src1_is_broadcast;
             id_src2[dim - 1] += !src2_is_broadcast;
+            ++id_dst[dim - 1];
         }
     }
 };
index 37713c841dd4b36423aaf6e1e7d941707692a277..6623b22e789dc5512e674164b3f1ba5596e217ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -46,7 +46,9 @@ SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const Simp
     const auto rows       = static_cast<int>(src.shape()[1]);
     const auto depth      = static_cast<int>(src.shape()[2]);
     const int  upper_dims = src.shape().total_size() / (cols * rows * depth);
-
+#if defined(_OPENMP)
+    #pragma omp parallel for schedule(dynamic, 1) collapse(4)
+#endif /* _OPENMP */
     for(int r = 0; r < upper_dims; ++r)
     {
         for(int i = 0; i < depth; ++i)
index 6fc46b402b71af8ae2507735544f67f4f5d44737..356c27ee1354160e2258a66bdddf95aa24420084 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -35,7 +35,9 @@ template <typename T>
 SimpleTensor<T> bitwise_and(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2)
 {
     SimpleTensor<T> dst(src1.shape(), src1.data_type());
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src1.num_elements(); ++i)
     {
         dst[i] = src1[i] & src2[i];
index 5a6a13b56c86cea39edb8b2b73a7ab89d0a070c7..03578a3bebc61a746b850fd3b6f23088fb140dda 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -35,7 +35,9 @@ template <typename T>
 SimpleTensor<T> bitwise_not(const SimpleTensor<T> &src)
 {
     SimpleTensor<T> dst(src.shape(), src.data_type());
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = ~src[i];
index fc258d54f1270eadb9fadc1677022745ade2ab42..11c0a932fe556965644e73b9ee73ddf4b26022a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -35,7 +35,9 @@ template <typename T>
 SimpleTensor<T> bitwise_or(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2)
 {
     SimpleTensor<T> dst(src1.shape(), src1.data_type());
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src1.num_elements(); ++i)
     {
         dst[i] = src1[i] | src2[i];
index b8d275d8b59ccd7bc484e88bf24d4fa80cd52305..afae032b1b87368f6638c0592667284a35761b9a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -35,7 +35,9 @@ template <typename T>
 SimpleTensor<T> bitwise_xor(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2)
 {
     SimpleTensor<T> dst(src1.shape(), src1.data_type());
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src1.num_elements(); ++i)
     {
         dst[i] = src1[i] ^ src2[i];
index e09bcff1c6a8c19acdf785e65b0bbe014aeef99c..89182f1a9c9666eed2d6af745de36cb6bdc47937 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,7 +57,9 @@ SimpleTensor<T> bounding_box_transform(const SimpleTensor<T> &boxes, const Simpl
 
     const size_t box_fields   = 4;
     const size_t class_fields = 4;
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(size_t i = 0; i < num_boxes; ++i)
     {
         // Extract ROI information
index 153f26a5c668b67c39020f8219498e7cb6b1bc5e..7ea3f1fe99f26fe4399fdeef105df6b6e33130de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -41,6 +41,9 @@ SimpleTensor<T> box3x3(const SimpleTensor<T> &src, BorderMode border_mode, T con
     const std::array<T, 9> filter{ { 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
     const float    scale        = 1.f / static_cast<float>(filter.size());
     const uint32_t num_elements = src.num_elements();
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
     {
         const Coordinates id = index2coord(src.shape(), element_idx);
index a6c0557b79001903662debbc88fa9d076e9d8bd4..2380b58583217de1adb3f911e0dd046ef51ab2fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -92,6 +92,9 @@ std::vector<SimpleTensor<T>> channel_combine(const TensorShape &shape, const std
 {
     std::vector<SimpleTensor<T>> dst = create_image_planes<T>(shape, format);
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(unsigned int plane_idx = 0; plane_idx < dst.size(); ++plane_idx)
     {
         SimpleTensor<T> &dst_tensor   = dst[plane_idx];
index fc7ae7d6cb2e4d0d02af038561746e53b3e83aee..75d0a00604da0d104f059b96a2527a40f33eab34 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -51,6 +51,9 @@ SimpleTensor<uint8_t> channel_extract(const TensorShape &shape, const std::vecto
     const int height = dst.shape().y();
 
     // Loop over each pixel and extract channel
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(2)
+#endif /* _OPENMP */
     for(int y = 0; y < height; ++y)
     {
         for(int x = 0; x < width; ++x)
index b8aa9203abcfde7b9439218c6e10cea6128a5727..39d89e9f020ab58477cec09f9393bbf5d244ebd6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -50,7 +50,9 @@ SimpleTensor<T> channel_shuffle(const SimpleTensor<T> &src, int num_groups)
 
     const T *src_ref = src.data();
     T       *dst_ref = dst.data();
-
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(2)
+#endif /* _OPENMP */
     for(int n = 0; n < batches; ++n)
     {
         for(int g = 0; g < num_groups; ++g)
index 53969d47253aa593bd1ee4cd08162aa336121010..f42582bbe8223b790b41e075ccfc3a094e6504ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -47,21 +47,26 @@ SimpleTensor<T> col2im(const SimpleTensor<T> &src, const TensorShape &dst_shape,
     if(num_groups == 1)
     {
         // Batches are on the 3rd dimension of the input tensor
-        int dst_idx = 0;
+#if defined(_OPENMP)
+        #pragma omp parallel for collapse(3)
+#endif /* _OPENMP */
         for(size_t b = 0; b < batches; ++b)
         {
             for(size_t x = 0; x < src_width; ++x)
             {
                 for(size_t y = 0; y < src_height; ++y)
                 {
-                    dst[dst_idx++] = src[coord2index(src.shape(), Coordinates(x, y, b))];
+                    const int dst_idx = y + x * src_height + b * src_height * src_width;
+                    dst[dst_idx]      = src[coord2index(src.shape(), Coordinates(x, y, b))];
                 }
             }
         }
     }
     else
     {
-        int dst_idx = 0;
+#if defined(_OPENMP)
+        #pragma omp parallel for collapse(4)
+#endif /* _OPENMP */
         for(size_t b = 0; b < batches; ++b)
         {
             for(size_t g = 0; g < num_groups; ++g)
@@ -70,7 +75,8 @@ SimpleTensor<T> col2im(const SimpleTensor<T> &src, const TensorShape &dst_shape,
                 {
                     for(size_t y = 0; y < src_height; ++y)
                     {
-                        dst[dst_idx++] = src[coord2index(src.shape(), Coordinates(x, y, g, b))];
+                        const int dst_idx = y + x * src_height + g * src_height * src_width + b * src_height * src_width * num_groups;
+                        dst[dst_idx]      = src[coord2index(src.shape(), Coordinates(x, y, g, b))];
                     }
                 }
             }
index c0c86b1933540327d5208517a483046e3630e9fd..2313d9b022210c91f22cb6e4f3588d7e17febb2c 100644 (file)
@@ -80,13 +80,16 @@ struct BroadcastUnroll
         id_src1.set(dim - 1, 0);
         id_src2.set(dim - 1, 0);
         id_dst.set(dim - 1, 0);
-
-        for(size_t i = 0; i < dst.shape()[dim - 1]; ++i, ++id_dst[dim - 1])
+#if defined(_OPENMP)
+        #pragma omp parallel for
+#endif /* _OPENMP */
+        for(size_t i = 0; i < dst.shape()[dim - 1]; ++i)
         {
             BroadcastUnroll < dim - 1 >::unroll(op, src1, src2, dst, id_src1, id_src2, id_dst);
 
             id_src1[dim - 1] += !src1_is_broadcast;
             id_src2[dim - 1] += !src2_is_broadcast;
+            ++id_dst[dim - 1];
         }
     }
 };
index 60be7ef8a89f361b38695246a27132a112622e5f..9654da2ea358d5361f2eb2c0784e4b4b82ea03a4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 ARM Limited.
+ * Copyright (c) 2019-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -49,6 +49,9 @@ SimpleTensor<T> compute_all_anchors(const SimpleTensor<T> &anchors, const Comput
     T              *all_anchors_ptr = all_anchors.data();
 
     // Iterate over the input grid and anchors
+#if defined(_OPENMP)
+    #pragma omp parallel for schedule(dynamic, 1) collapse(3)
+#endif /* _OPENMP */
     for(int y = 0; y < height; y++)
     {
         for(int x = 0; x < width; x++)
index 5925496f454273d23a448558b19390e9782fcbbf..710644a4e59c7fd95c592ada113a191655d294c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -49,6 +49,9 @@ SimpleTensor<T> convert_fully_connected_weights(const SimpleTensor<T> &src, cons
     const unsigned int factor_2                  = is_nchw_to_nhwc ? num_channels : num_elems_per_input_plane;
 
     const uint32_t num_elements = src.num_elements();
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t i = 0; i < num_elements; ++i)
     {
         const Coordinates coords_in = index2coords(src.shape(), i);
index 5e0f29d421d10c71bf53023e31e315d85f1afd55..ad93b3077aa18951eabb624b1eb59fa78daa75a7 100644 (file)
@@ -45,6 +45,9 @@ SimpleTensor<T> convolution(const SimpleTensor<uint8_t> &src, DataType output_da
     SimpleTensor<T>       dst(src.shape(), output_data_type);
     SimpleTensor<int32_t> sum(src.shape(), output_data_type);
     const uint32_t        num_elements = src.num_elements();
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
     {
         const Coordinates id = index2coord(src.shape(), element_idx);
index 84fb3491bd7312e5c8b0c23e3197b2347637e155..aed976e5ee95f26076c659489724c5d64e14f861 100644 (file)
@@ -69,6 +69,9 @@ SimpleTensor<T> convolution_layer_nchw(const SimpleTensor<T> &src, const SimpleT
     const int end_xi      = output_wh.first * stride_xi;
     const int end_yi      = output_wh.second * stride_yi;
     const int num_batches = src.shape().total_size() / (width_in * height_in * depth_in);
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(5)
+#endif /* _OPENMP */
     for(int r = 0; r < num_batches; ++r)
     {
         for(int yi = start_yi; yi < start_yi + end_yi; yi += stride_yi)
index b3c2c6b0b98a950fdd9f07a340284c0b6d7c2de1..ae030c71046d8bc71674a4082c760b6331aabd14 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 ARM Limited.
+ * Copyright (c) 2019-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -50,6 +50,9 @@ namespace
 template <typename T>
 void rdft_1d_step(const T *src_ptr, size_t N, T *dst_ptr, size_t K)
 {
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(unsigned int k = 0; k < K; ++k)
     {
         float Xr = 0;
@@ -77,6 +80,9 @@ void rdft_1d_step(const T *src_ptr, size_t N, T *dst_ptr, size_t K)
 template <typename T>
 void dft_1d_step(const T *src_ptr, T *dst_ptr, size_t N)
 {
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(unsigned int k = 0; k < N; ++k)
     {
         float Xr = 0;
@@ -111,7 +117,9 @@ void irdft_1d_step(const T *src_ptr, size_t K, T *dst_ptr, size_t N)
     const bool         is_odd     = N % 2;
     const unsigned int Nleft      = N - K;
     const int          tail_start = is_odd ? K - 1 : K - 2;
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(unsigned int n = 0; n < N; ++n)
     {
         float xr = 0;
@@ -142,6 +150,9 @@ void irdft_1d_step(const T *src_ptr, size_t K, T *dst_ptr, size_t N)
 template <typename T>
 void idft_1d_step(const T *src_ptr, T *dst_ptr, size_t N)
 {
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(unsigned int n = 0; n < N; ++n)
     {
         float xr = 0;
@@ -181,6 +192,9 @@ SimpleTensor<T> rdft_1d_core(const SimpleTensor<T> &src, FFTDirection direction,
     SimpleTensor<T> dst(dst_shape, src.data_type(), num_channels);
 
     const unsigned int upper_dims = src.shape().total_size_upper(1);
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(unsigned int du = 0; du < upper_dims; ++du)
     {
         const T *src_row_ptr = src.data() + du * N * src.num_channels();
@@ -201,6 +215,9 @@ SimpleTensor<T> dft_1d_core(const SimpleTensor<T> &src, FFTDirection direction)
     SimpleTensor<T> dst(src.shape(), src.data_type(), src.num_channels());
 
     const unsigned int upper_dims = src.shape().total_size_upper(1);
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(unsigned int du = 0; du < upper_dims; ++du)
     {
         const T *src_row_ptr = src.data() + du * N * src.num_channels();
@@ -221,6 +238,9 @@ void scale(SimpleTensor<T> &tensor, T scaling_factor)
 {
     const int total_elements = tensor.num_elements() * tensor.num_channels();
     T        *data_ptr       = tensor.data();
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < total_elements; ++i)
     {
         data_ptr[i] /= scaling_factor;
@@ -249,7 +269,9 @@ SimpleTensor<T> complex_mul_and_reduce(const SimpleTensor<T> &input, const Simpl
 
     // MemSet dst memory to zero
     std::memset(dst.data(), 0, dst.size());
-
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(5)
+#endif /* _OPENMP */
     for(uint32_t b = 0; b < N; ++b)
     {
         for(uint32_t co = 0; co < Co; ++co)
index 5750f51e3f6eb3a261103c99db0f9814af769819..01b9c1c40369f5912cbebf1694356023475fff19 100644 (file)
@@ -100,6 +100,9 @@ SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTens
 
     // Flip weights by 180 degrees
     SimpleTensor<T> weights_flipped{ weights.shape(), weights.data_type(), 1, weights.quantization_info() };
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int ud = 0; ud < weights_upper_dims; ++ud)
     {
         const int offset = ud * weights_width * weights_height;
@@ -111,7 +114,9 @@ SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTens
             }
         }
     }
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int slice = 0; slice < num_2d_slices; ++slice)
     {
         const int offset_slice_in  = slice * width_in * height_in;
index d6e6e78187eecf1ede8c300153940ccdff1a723f..2c93e7060ab58490d103e47c0e65cd080ce24459 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -58,6 +58,9 @@ SimpleTensor<T> depthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs,
 
     if(srcs[0].data_type() == DataType::QASYMM8 && std::any_of(srcs.cbegin(), srcs.cend(), have_different_quantization_info))
     {
+#if defined(_OPENMP)
+        #pragma omp parallel for
+#endif /* _OPENMP */
         for(int b = 0; b < batches; ++b)
         {
             // input tensors can have smaller width and height than the output, so for each output's slice we need to requantize 0 (as this is the value
index 57eeb7f6f35cf9e5a5be1667c54ae86048490836..9c6a9aa76c4f2d4f8c8c8fe29bcd019c4615c49a 100644 (file)
@@ -46,6 +46,9 @@ SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, Con
     // Up-casting
     if(element_size_from_data_type(src.data_type()) < element_size_from_data_type(dt_out))
     {
+#if defined(_OPENMP)
+        #pragma omp parallel for
+#endif /* _OPENMP */
         for(int i = 0; i < src.num_elements(); ++i)
         {
             result[i] = src[i] << shift;
@@ -54,6 +57,9 @@ SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, Con
     // Down-casting
     else
     {
+#if defined(_OPENMP)
+        #pragma omp parallel for
+#endif /* _OPENMP */
         for(int i = 0; i < src.num_elements(); ++i)
         {
             T1 val    = src[i] >> shift;
index 4135ce54710dc843c541e4a4af29fe82186271d0..e2329ed60b3d5cef38f4663120e33580ebd4ce82 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 ARM Limited.
+ * Copyright (c) 2019-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -40,13 +40,14 @@ SimpleTensor<T> depth_to_space(const SimpleTensor<T> &src, const TensorShape &ds
     ARM_COMPUTE_ERROR_ON(block_shape <= 0);
     SimpleTensor<T> result(dst_shape, src.data_type());
 
-    int        in_pos     = 0;
     const auto width_in   = static_cast<int>(src.shape()[0]);
     const auto height_in  = static_cast<int>(src.shape()[1]);
     const auto channel_in = static_cast<int>(src.shape()[2]);
     const auto batch_in   = static_cast<int>(src.shape()[3]);
     const int  r          = channel_in / (block_shape * block_shape);
-
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(4)
+#endif /* _OPENMP */
     for(int b = 0; b < batch_in; ++b)
     {
         for(int z = 0; z < channel_in; ++z)
@@ -58,8 +59,8 @@ SimpleTensor<T> depth_to_space(const SimpleTensor<T> &src, const TensorShape &ds
                     const int out_x   = (block_shape * x + (z / r) % block_shape);
                     const int out_y   = (block_shape * y + (z / r) / block_shape);
                     const int out_pos = out_x + dst_shape[0] * out_y + (z % r) * dst_shape[0] * dst_shape[1] + b * dst_shape[0] * dst_shape[1] * dst_shape[2];
+                    const int in_pos  = x + width_in * y + z * width_in * height_in + b * width_in * height_in * channel_in;
                     result[out_pos]   = src[in_pos];
-                    ++in_pos;
                 }
             }
         }
index 7dd36402b360aef6b055ad26b1720acfe092d5e5..7dec988b180c39bcc1707d6808fed7e55a1f3f07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -75,7 +75,9 @@ SimpleTensor<TOut> dequantization_layer(const SimpleTensor<TIn> &src)
         const int N  = src.shape().total_size() / (WH * C);
 
         const std::vector<float> qscales = src.quantization_info().scale();
-
+#if defined(_OPENMP)
+        #pragma omp parallel for collapse(2)
+#endif /* _OPENMP */
         for(int n = 0; n < N; ++n)
         {
             for(int c = 0; c < C; ++c)
@@ -95,7 +97,9 @@ SimpleTensor<TOut> dequantization_layer(const SimpleTensor<TIn> &src)
     {
         const UniformQuantizationInfo &quantization_info = src.quantization_info().uniform();
         ARM_COMPUTE_ERROR_ON(quantization_info.offset != 0 && src_data_type == DataType::QSYMM8);
-
+#if defined(_OPENMP)
+        #pragma omp parallel for
+#endif /* _OPENMP */
         for(int i = 0; i < src.num_elements(); ++i)
         {
             dst[i] = static_cast<TOut>(dequantize<TOut>(static_cast<TIn>(src[i]), quantization_info, src_data_type));
index 3c6f3259b2fdbe17f240a4b52a607acb35cace87..f4c2934728645203e1eed1e9f717a31ef55e80ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -62,6 +62,9 @@ std::pair<SimpleTensor<T>, SimpleTensor<T>> derivative(const SimpleTensor<U> &sr
     ValidRegion valid_region = shape_to_valid_region(src.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(filter_size / 2));
 
     const uint32_t num_elements = src.num_elements();
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t i = 0; i < num_elements; ++i)
     {
         Coordinates coord = index2coord(src.shape(), i);
index 8e244e9b7b4ede1850fc0cae98855899af94af4d..cba9af127f225713a492f7953bbc96aeaab591f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +52,9 @@ SimpleTensor<T> dilate(const SimpleTensor<T> &src, BorderMode border_mode, T con
     SimpleTensor<T> dst(src.shape(), src.data_type());
     const uint32_t  num_elements = src.num_elements();
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t i = 0; i < num_elements; ++i)
     {
         Coordinates coord = index2coord(src.shape(), i);
index eaaaa4ec1e4d6fd6dac0dd92bfdfe8df48f3dad6..f1bb7c783c7827b9281a333f7b98cb02275a1acd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
index 1a10c2c30a00078e1d34ede584771f82095c2e9e..34e7c397bf9c7215fa334644133d312652e75d4c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -75,6 +75,9 @@ SimpleTensor<T> equalize_histogram(const SimpleTensor<T> &src)
     }
 
     // Fill output tensor with equalized values
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = lut[src[i]];
index e7598c3900c3b1887cb21cf8642c982c2e5263c2..0964c3d4b234fc58c434b9b084146a810e4a95cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +52,9 @@ SimpleTensor<T> erode(const SimpleTensor<T> &src, BorderMode border_mode, T cons
     SimpleTensor<T> dst(src.shape(), src.data_type());
 
     const uint32_t num_elements = src.num_elements();
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t i = 0; i < num_elements; ++i)
     {
         Coordinates coord = index2coord(src.shape(), i);
index b011a169740ae49ca230ffb9ff83bb61e13a037d..21fa1c9932d9d3cf135c0c737a3836dd025bd11f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -42,6 +42,9 @@ SimpleTensor<T> floor_layer(const SimpleTensor<T> &src)
     SimpleTensor<T> dst{ src.shape(), src.data_type() };
 
     // Compute reference
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < src.num_elements(); ++i)
     {
         dst[i] = std::floor(src[i]);
index 9aecd6cf14e7183cc871a7027c06d237ecdd0598..908c5831619faa0fa7906b32b84fdd7adf860dff 100644 (file)
@@ -49,11 +49,12 @@ void vector_matrix_multiply(const SimpleTensor<T> &src, const SimpleTensor<T> &w
     const T *weights_ptr = weights.data();
     const TB *bias_ptr    = bias.data();
     T        *dst_ptr     = dst.data() + offset_dst;
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int y = 0; y < rows_weights; ++y)
     {
-        dst_ptr[y] = std::inner_product(src_ptr, src_ptr + cols_weights, weights_ptr, static_cast<T>(0)) + bias_ptr[y];
-        weights_ptr += cols_weights;
+        dst_ptr[y] = std::inner_product(src_ptr, src_ptr + cols_weights, &weights_ptr[cols_weights * y], static_cast<T>(0)) + bias_ptr[y];
     }
 }
 
@@ -85,7 +86,9 @@ void vector_matrix_multiply(const SimpleTensor<T> &src, const SimpleTensor<T> &w
 
     const int min = std::numeric_limits<T>::lowest();
     const int max = std::numeric_limits<T>::max();
-
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int y = 0; y < rows_weights; ++y)
     {
         // Reset accumulator
@@ -93,7 +96,7 @@ void vector_matrix_multiply(const SimpleTensor<T> &src, const SimpleTensor<T> &w
 
         for(int x = 0; x < cols_weights; ++x)
         {
-            acc += (src_ptr[x] + input_offset) * (weights_ptr[x] + weights_offset);
+            acc += (src_ptr[x] + input_offset) * (weights_ptr[x + y * cols_weights] + weights_offset);
         }
 
         // Accumulate the bias
@@ -104,8 +107,6 @@ void vector_matrix_multiply(const SimpleTensor<T> &src, const SimpleTensor<T> &w
 
         // Store the result
         dst_ptr[y] = static_cast<T>(acc);
-
-        weights_ptr += cols_weights;
     }
 }
 } // namespace
index df12b25912cac0743315a4868e598173f13ab198..cb5003874b759d6e11e4a1574646ab635994bbf6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 ARM Limited.
+ * Copyright (c) 2019-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -22,6 +22,7 @@
  * SOFTWARE.
  */
 #include "FuseBatchNormalization.h"
+#include "tests/validation/Helpers.h"
 
 namespace arm_compute
 {
@@ -45,6 +46,9 @@ void fuse_batch_normalization_dwc_layer(const SimpleTensor<T> &w, const SimpleTe
     const unsigned int height = w.shape()[1];
     const unsigned int dim2   = w.shape()[2];
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(unsigned int b = 0; b < dim2; ++b)
     {
         const auto mean_val  = mean.data()[b];
index 3c72b94143fd7b13fcadb9be51ce3ff099591d55..20def87a64e8930e0ca131eb89f13b8eb1db9314 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -23,6 +23,7 @@
  */
 #include "GEMM.h"
 
+#include "arm_compute/core/Helpers.h"
 #include "arm_compute/core/Types.h"
 
 namespace arm_compute
@@ -55,6 +56,9 @@ SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const S
     const int c_stride_z = N * M;
     const int c_stride_w = N * M * D;
 
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(2)
+#endif /* _OPENMP */
     for(int w = 0; w < W; ++w)
     {
         for(int depth = 0; depth < D; ++depth)
@@ -107,6 +111,9 @@ SimpleTensor<T> gemm_mixed_precision(const SimpleTensor<T> &a, const SimpleTenso
     const int c_stride_z = N * M;
     const int c_stride_w = N * M * D;
 
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(2)
+#endif /* _OPENMP */
     for(int w = 0; w < W; ++w)
     {
         for(int depth = 0; depth < D; ++depth)
index 36d86d1532cb0a0aff46b431110ca962bc9ccdb1..85a98e4a7681ef5b2ea9b0a3786c26dcfa9f2452 100644 (file)
@@ -69,6 +69,9 @@ void quantize_down_scale(const SimpleTensor<TIn> *in, const SimpleTensor<TIn> *b
     const int  cols_in        = in->shape().x();
     const bool is_per_channel = result_mult_int.size() > 1;
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < in->num_elements(); ++i)
     {
         int32_t result = ((*in)[i] + result_offset);
@@ -100,6 +103,9 @@ void quantize_down_scale_by_fixedpoint(const SimpleTensor<TIn> *in, const Simple
     const int  cols_in        = in->shape().x();
     const bool is_per_channel = result_fixedpoint_multiplier.size() > 1;
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < in->num_elements(); ++i)
     {
         TIn result = (*in)[i];
@@ -141,6 +147,9 @@ void quantize_down_scale_by_float(const SimpleTensor<TIn> *in, const SimpleTenso
     const int  cols_in        = in->shape().x();
     const bool is_per_channel = result_real_multiplier.size() > 1;
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int i = 0; i < in->num_elements(); ++i)
     {
         TIn result = (*in)[i];
index 431d65696e46e455b0761aab790ed2513a41827d..f21fe50e58a39b8346641c44e40580fd64a6ebe3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
index 0224c5c67c1f571fd5db7f3a0c0df6cdcd0aa777..ebb6f856d2b54d3397ae04b80c1e750141990dcb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -70,7 +70,9 @@ SimpleTensor<T> gemm_reshape_rhs_matrix(const SimpleTensor<T> &in, const TensorS
 
     const unsigned int offset_output_x = rhs_info.interleave ? tile_to_use->shape()[0] : tile_to_use->shape()[0] * tile_to_use->shape()[1];
     const unsigned int step_output_x   = rhs_info.interleave ? tile_to_use->shape()[0] * rhs_info.h0 : tile_to_use->shape()[0];
-
+#ifdef ARM_COMPUTE_OPENMP
+    #pragma omp parallel for schedule(dynamic, 1) collapse(3)
+#endif /* _OPENMP */
     for(unsigned int z = 0; z < B; ++z)
     {
         for(unsigned int y = 0; y < num_tiles_y; ++y)
index 5ca24a7961e2871fcd723c85b2033576ed6bbbed..f2ac134f17b60da5dc263a493a7b5cfe4a23d2b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -42,6 +42,9 @@ SimpleTensor<T> gaussian3x3(const SimpleTensor<T> &src, BorderMode border_mode,
     const float    scale        = 1.f / 16.f;
     const uint32_t num_elements = src.num_elements();
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
     {
         const Coordinates id = index2coord(src.shape(), element_idx);
index ac84f6d097cec481ddcd7abe9dd59c8b58eadaec..426e66647c8b018e43c17d9ec96d81c1809bffd2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -48,6 +48,9 @@ SimpleTensor<T> gaussian5x5(const SimpleTensor<T> &src, BorderMode border_mode,
     const float    scale        = 1.f / 256.f;
     const uint32_t num_elements = src.num_elements();
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
     {
         const Coordinates id = index2coord(src.shape(), element_idx);
index 4b41cdb70b54965d79609ed8b638e8b55c2713b1..a3dcf072733951bb5dbdecb15696769dca921e3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -109,7 +109,9 @@ void im2col_nhwc(const SimpleTensor<T> &src, SimpleTensor<T> &dst, const Size2D
 
     // Compute width and height of the convolved tensors
     std::pair<unsigned int, unsigned int> convolved_dims = scaled_dimensions(src_width, src_height, kernel_dims.width, kernel_dims.height, conv_info);
-
+#if defined(_OPENMP)
+    #pragma omp parallel for schedule(dynamic, 1) collapse(2)
+#endif /* _OPENMP */
     for(int b = 0; b < batches; ++b)
     {
         for(int yo = 0; yo < dst_height; ++yo)
index ad0ac1be689efdda06f9bcc442abacfd2f767053..339549723dc332ad5b943eeb121f7ab0c54c14a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 ARM Limited.
+ * Copyright (c) 2019-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -46,12 +46,14 @@ SimpleTensor<T> instance_normalization(const SimpleTensor<T> &src, float gamma,
     const size_t h_size = src.shape()[1];
     const size_t c_size = src.shape()[2];
     const size_t n_size = src.shape()[3];
-
+#if defined(_OPENMP)
+    #pragma omp parallel for collapse(2)
+#endif /* _OPENMP */
     for(size_t n_i = 0; n_i < n_size; ++n_i)
     {
         for(size_t c_i = 0; c_i < c_size; ++c_i)
         {
-            float sum_h_w = 0;
+            float sum_h_w    = 0;
             float sum_sq_h_w = 0;
 
             for(size_t h_i = 0; h_i < h_size; ++h_i)
@@ -60,13 +62,14 @@ SimpleTensor<T> instance_normalization(const SimpleTensor<T> &src, float gamma,
                 {
                     float val = src[coord2index(src.shape(), Coordinates(w_i, h_i, c_i, n_i))];
                     sum_h_w += val;
-                    sum_sq_h_w += val*val;
+                    sum_sq_h_w += val * val;
                 }
             }
             //Compute mean
             const float mean_h_w = sum_h_w / (h_size * w_size);
             //Compute variance
-            const float var_h_w = sum_sq_h_w / (h_size * w_size) - mean_h_w * mean_h_w;;
+            const float var_h_w = sum_sq_h_w / (h_size * w_size) - mean_h_w * mean_h_w;
+            ;
 
             //Apply mean
             for(size_t h_i = 0; h_i < h_size; ++h_i)
index cfc508529ec19c3beca74901bb8adb7a54e6ab68..a70523d7da855a6142e47de44519014056e74fbd 100644 (file)
@@ -50,12 +50,18 @@ SimpleTensor<Tout> quantization_layer(const SimpleTensor<Tin> &src, DataType out
     switch(output_data_type)
     {
         case DataType::QASYMM8:
+#if defined(_OPENMP)
+            #pragma omp parallel for
+#endif /* _OPENMP */
             for(int i = 0; i < src.num_elements(); ++i)
             {
                 dst[i] = quantize_qasymm8((src[i]), qinfo, rounding_policy);
             }
             break;
         case DataType::QASYMM8_SIGNED:
+#if defined(_OPENMP)
+            #pragma omp parallel for
+#endif /* _OPENMP */
             for(int i = 0; i < src.num_elements(); ++i)
             {
 #ifdef __aarch64__
@@ -66,6 +72,9 @@ SimpleTensor<Tout> quantization_layer(const SimpleTensor<Tin> &src, DataType out
             }
             break;
         case DataType::QASYMM16:
+#if defined(_OPENMP)
+            #pragma omp parallel for
+#endif /* _OPENMP */
             for(int i = 0; i < src.num_elements(); ++i)
             {
                 dst[i] = quantize_qasymm16((src[i]), qinfo, rounding_policy);
index 2eb5d01926217df559f116cfaf311ad3f4eeaa94..9f087d06cb88f8f6c9301336da29462db79af81e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -54,6 +54,10 @@ SimpleTensor<T> reorg_layer(const SimpleTensor<T> &src, int32_t stride)
 
     // Calculate layer reorg in NCHW
     Coordinates map_coords;
+
+#if defined(_OPENMP)
+    #pragma omp parallel for private(map_coords)
+#endif /* _OPENMP */
     for(unsigned int b = 0; b < outer_dims; ++b)
     {
         map_coords.set(3, b);
index 4bd8efc6a811b3d25a010ca4db443bcd038fd0ea..f5630b9a40c6bd53e39b6acfb66ac37102736748 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -55,6 +55,10 @@ SimpleTensor<T> reverse(const SimpleTensor<T> &src, const SimpleTensor<uint32_t>
     }
 
     const uint32_t num_elements = src.num_elements();
+
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t i = 0; i < num_elements; ++i)
     {
         const Coordinates  src_coord = index2coord(src.shape(), i);
index 0e470260a9db37923f42464918adc82b875698b1..ee7a5f175a5713cea3e077a14f737d7e37681d3b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -55,6 +55,9 @@ SimpleTensor<T> softmax_layer_generic(const SimpleTensor<T> &src, float beta, si
         upper_dims *= src.shape()[i];
     }
 
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(int r = 0; r < upper_dims; ++r)
     {
         const T *src_row_ptr = src.data() + r * lower_dims;
@@ -107,7 +110,7 @@ SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src, float beta, size_t axi
     return softmax_layer_generic<T>(src, beta, axis, false);
 }
 
-template <typename T, typename std::enable_if<std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value, int>::type>
+template < typename T, typename std::enable_if < std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value, int >::type >
 SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src, float beta, size_t axis)
 {
     const QuantizationInfo output_quantization_info = arm_compute::get_softmax_output_quantization_info(src.data_type(), false);
index 47f5ac7a7de45fcd5952e9737e582feb09e2e0dc..61ba510fc6c69acd0c31ead67c3bd64c55f1aa7d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
index 0011b85c1e06e19e69a8f57cdd9314813fafa5a7..92bbf5445ff490dfd5021b5e0e6cf5332f7e2311 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -47,6 +47,9 @@ SimpleTensor<T> yolo_layer(const SimpleTensor<T> &src, const ActivationLayerInfo
     const T b(info.b());
 
     const uint32_t num_elements = src.num_elements();
+#if defined(_OPENMP)
+    #pragma omp parallel for
+#endif /* _OPENMP */
     for(uint32_t i = 0; i < num_elements; ++i)
     {
         const size_t z = index2coord(dst.shape(), i).z() % (num_classes + 5);