aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeorgios Pinitas <georgios.pinitas@arm.com>2017-12-01 16:13:40 +0000
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:42:17 +0000
commit8795ffb03c1bb84a0d93e4ece153ceaa86118594 (patch)
tree87d6fec8a6422dd195a79c38bbe170afd7106fc3 /src
parentab4907325ea264efc26b89ebad7e10522cb823e5 (diff)
downloadComputeLibrary-8795ffb03c1bb84a0d93e4ece153ceaa86118594.tar.gz
COMPMID-700: Adds CPPPermute function
Change-Id: I8f6adc67f6e6157710fca540f217d70e6f297217 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/111721 Tested-by: BSG Visual Compute Jenkins server to access repositories on http://mpd-gerrit.cambridge.arm.com <bsgcomp@arm.com> Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/CPP/kernels/CPPPermuteKernel.cpp169
-rw-r--r--src/core/NEON/kernels/NEMinMaxLocationKernel.cpp35
-rw-r--r--src/runtime/CPP/ICPPSimpleFunction.cpp38
-rw-r--r--src/runtime/CPP/functions/CPPPermute.cpp41
4 files changed, 256 insertions, 27 deletions
diff --git a/src/core/CPP/kernels/CPPPermuteKernel.cpp b/src/core/CPP/kernels/CPPPermuteKernel.cpp
new file mode 100644
index 0000000000..55cc00ffbf
--- /dev/null
+++ b/src/core/CPP/kernels/CPPPermuteKernel.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 "arm_compute/core/CPP/kernels/CPPPermuteKernel.h"
+
+#include "arm_compute/core/Error.h"
+#include "arm_compute/core/Helpers.h"
+#include "arm_compute/core/ITensor.h"
+#include "arm_compute/core/TensorInfo.h"
+#include "arm_compute/core/Types.h"
+#include "arm_compute/core/Validate.h"
+
+#include <cstddef>
+#include <cstdint>
+
+using namespace arm_compute;
+
+namespace
+{
+TensorShape get_output_shape(const ITensorInfo *input, const PermutationVector &perm)
+{
+ TensorShape output_shape = input->tensor_shape();
+ permute(output_shape, perm);
+ return output_shape;
+}
+
+Error validate_arguments(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::U8, DataType::S8, DataType::QS8, DataType::QASYMM8,
+ DataType::U16, DataType::S16, DataType::QS16,
+ DataType::U32, DataType::S32,
+ DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(input->num_dimensions() < 3, "Invalid input size!");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(perm.num_dimensions() != 3 && ((perm[0] != 2 && perm[1] != 0 && perm[2] != 1) || (perm[0] != 1 && perm[1] != 2 && perm[2] != 0)),
+ "Only [2, 0, 1] and [1, 2, 0] permutation is supported");
+
+ // Validate configured output
+ if(output->total_size() != 0)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output->tensor_shape(), get_output_shape(input, perm));
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(input, output);
+ }
+
+ return Error{};
+}
+} // namespace
+
+template <typename T>
+void CPPPermuteKernel::run_permute(const Window &window)
+{
+ const int output_stride_x = _output->info()->strides_in_bytes().x();
+ const int output_stride_y = _output->info()->strides_in_bytes().y();
+ const int output_stride_z = _output->info()->strides_in_bytes().z();
+
+ Window window_out(window);
+ window_out.set(Window::DimX, Window::Dimension(0, 0, 0));
+ window_out.set(Window::DimY, Window::Dimension(0, 0, 0));
+ window_out.set(Window::DimZ, Window::Dimension(0, 0, 0));
+
+ // Create iterators
+ Iterator in(_input, window);
+ Iterator out(_output, window_out);
+
+ // Run [2, 0, 1] permute
+ if(_perm[0] == 2 && _perm[1] == 0 && _perm[2] == 1)
+ {
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ const int idx = id.y() * output_stride_z + id.x() * output_stride_y + id.z() * output_stride_x;
+ *(reinterpret_cast<T *>(out.ptr() + idx)) = *(reinterpret_cast<const T *>(in.ptr()));
+ },
+ in, out);
+ }
+ // Run [1, 2, 0] permute
+ else
+ {
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ const int idx = id.x() * output_stride_z + id.z() * output_stride_y + id.y() * output_stride_x;
+ *(reinterpret_cast<T *>(out.ptr() + idx)) = *(reinterpret_cast<const T *>(in.ptr()));
+ },
+ in, out);
+ }
+}
+
+CPPPermuteKernel::CPPPermuteKernel()
+ : _func(), _input(nullptr), _output(nullptr), _perm()
+{
+}
+
+void CPPPermuteKernel::configure(const ITensor *input, ITensor *output, const PermutationVector &perm)
+{
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
+
+ // Output auto inizialitation if not yet initialized
+ auto_init_if_empty(*output->info(), input->info()->clone()->set_tensor_shape(get_output_shape(input->info(), perm)));
+
+ // Perform validation step
+ ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), output->info(), perm));
+
+ _input = input;
+ _output = output;
+ _perm = perm;
+
+ switch(input->info()->element_size())
+ {
+ case 1:
+ _func = &CPPPermuteKernel::run_permute<uint8_t>;
+ break;
+ case 2:
+ _func = &CPPPermuteKernel::run_permute<uint16_t>;
+ break;
+ case 4:
+ _func = &CPPPermuteKernel::run_permute<uint32_t>;
+ break;
+ default:
+ ARM_COMPUTE_ERROR("Element size not supported");
+ break;
+ }
+
+ // Configure kernel window
+ Window win = calculate_max_window(*input->info(), Steps());
+
+ // The CPPPermute doesn't need padding so update_window_and_padding() can be skipped
+ Coordinates coord;
+ coord.set_num_dimensions(output->info()->num_dimensions());
+ output->info()->set_valid_region(ValidRegion(coord, output->info()->tensor_shape()));
+
+ ICPPKernel::configure(win);
+}
+
+Error CPPPermuteKernel::validate(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm)
+{
+ ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, output, perm));
+ return Error{};
+}
+
+void CPPPermuteKernel::run(const Window &window, const ThreadInfo &info)
+{
+ ARM_COMPUTE_UNUSED(info);
+ ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
+ ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICPPKernel::window(), window);
+
+ if(_func != nullptr)
+ {
+ (this->*_func)(window);
+ }
+}
diff --git a/src/core/NEON/kernels/NEMinMaxLocationKernel.cpp b/src/core/NEON/kernels/NEMinMaxLocationKernel.cpp
index c7dc03c8c8..ad66acd8fa 100644
--- a/src/core/NEON/kernels/NEMinMaxLocationKernel.cpp
+++ b/src/core/NEON/kernels/NEMinMaxLocationKernel.cpp
@@ -32,6 +32,7 @@
#include "arm_compute/core/Types.h"
#include "arm_compute/core/Validate.h"
#include "arm_compute/core/Window.h"
+#include "arm_compute/core/utils/misc/utility.h"
#include <algorithm>
#include <arm_neon.h>
@@ -319,34 +320,14 @@ bool NEMinMaxLocationKernel::is_parallelisable() const
return false;
}
-template <unsigned int...>
-struct index_seq
-{
- index_seq() = default;
- index_seq(const index_seq &) = default;
- index_seq &operator=(const index_seq &) = default;
- index_seq(index_seq &&) noexcept = default;
- index_seq &operator=(index_seq &&) noexcept = default;
- virtual ~index_seq() = default;
-};
-template <unsigned int N, unsigned int... S>
-struct gen_index_seq : gen_index_seq < N - 1, N - 1, S... >
-{
-};
-template <unsigned int... S>
-struct gen_index_seq<0u, S...> : index_seq<S...>
-{
- using type = index_seq<S...>;
-};
-
-template <class T, unsigned int... N>
-struct NEMinMaxLocationKernel::create_func_table<T, index_seq<N...>>
+template <class T, std::size_t... N>
+struct NEMinMaxLocationKernel::create_func_table<T, utility::index_sequence<N...>>
{
static const NEMinMaxLocationKernel::MinMaxLocFunction func_table[sizeof...(N)];
};
-template <class T, unsigned int... N>
-const NEMinMaxLocationKernel::MinMaxLocFunction NEMinMaxLocationKernel::create_func_table<T, index_seq<N...>>::func_table[sizeof...(N)] =
+template <class T, std::size_t... N>
+const NEMinMaxLocationKernel::MinMaxLocFunction NEMinMaxLocationKernel::create_func_table<T, utility::index_sequence<N...>>::func_table[sizeof...(N)] =
{
&NEMinMaxLocationKernel::minmax_loc<T, bool(N & 8), bool(N & 4), bool(N & 2), bool(N & 1)>...
};
@@ -378,13 +359,13 @@ void NEMinMaxLocationKernel::configure(const IImage *input, void *min, void *max
switch(input->info()->data_type())
{
case DataType::U8:
- _func = create_func_table<uint8_t, gen_index_seq<16>::type>::func_table[table_idx];
+ _func = create_func_table<uint8_t, utility::index_sequence_t<16>>::func_table[table_idx];
break;
case DataType::S16:
- _func = create_func_table<int16_t, gen_index_seq<16>::type>::func_table[table_idx];
+ _func = create_func_table<int16_t, utility::index_sequence_t<16>>::func_table[table_idx];
break;
case DataType::F32:
- _func = create_func_table<float, gen_index_seq<16>::type>::func_table[table_idx];
+ _func = create_func_table<float, utility::index_sequence_t<16>>::func_table[table_idx];
break;
default:
ARM_COMPUTE_ERROR("Unsupported data type");
diff --git a/src/runtime/CPP/ICPPSimpleFunction.cpp b/src/runtime/CPP/ICPPSimpleFunction.cpp
new file mode 100644
index 0000000000..42a2d2228c
--- /dev/null
+++ b/src/runtime/CPP/ICPPSimpleFunction.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 "arm_compute/runtime/CPP/ICPPSimpleFunction.h"
+
+#include "arm_compute/runtime/Scheduler.h"
+
+using namespace arm_compute;
+
+ICPPSimpleFunction::ICPPSimpleFunction() // NOLINT
+ : _kernel()
+{
+}
+
+void ICPPSimpleFunction::run()
+{
+ Scheduler::get().schedule(_kernel.get(), Window::DimY);
+}
diff --git a/src/runtime/CPP/functions/CPPPermute.cpp b/src/runtime/CPP/functions/CPPPermute.cpp
new file mode 100644
index 0000000000..5b92718542
--- /dev/null
+++ b/src/runtime/CPP/functions/CPPPermute.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 "arm_compute/runtime/CPP/functions/CPPPermute.h"
+
+#include "arm_compute/core/CPP/kernels/CPPPermuteKernel.h"
+#include "support/ToolchainSupport.h"
+
+using namespace arm_compute;
+
+void CPPPermute::configure(const ITensor *input, ITensor *output, const PermutationVector &perm)
+{
+ auto k = arm_compute::support::cpp14::make_unique<CPPPermuteKernel>();
+ k->configure(input, output, perm);
+ _kernel = std::move(k);
+}
+
+Error CPPPermute::validate(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm)
+{
+ return CPPPermuteKernel::validate(input, output, perm);
+}