From cac13b1cfd593889271f8e2191be2039b8d88f36 Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Fri, 27 Apr 2018 19:07:19 +0100 Subject: COMPMID-1097: Port mobilenet to NHWC Change-Id: I789065bfa0d4ef133388e1904c5caf31e450f80f Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/129495 Tested-by: Jenkins Reviewed-by: Anthony Barbier --- utils/GraphUtils.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 11 deletions(-) (limited to 'utils/GraphUtils.cpp') diff --git a/utils/GraphUtils.cpp b/utils/GraphUtils.cpp index 7912fd6b7d..145e44950b 100644 --- a/utils/GraphUtils.cpp +++ b/utils/GraphUtils.cpp @@ -24,6 +24,8 @@ #include "utils/GraphUtils.h" +#include "arm_compute/core/Helpers.h" +#include "arm_compute/core/Types.h" #include "arm_compute/runtime/SubTensor.h" #include "utils/Utils.h" @@ -31,6 +33,27 @@ using namespace arm_compute::graph_utils; +namespace +{ +std::pair compute_permutation_paramaters(const arm_compute::TensorShape &shape, + arm_compute::DataLayout data_layout) +{ + // Set permutation parameters if needed + arm_compute::TensorShape permuted_shape = shape; + arm_compute::PermutationVector perm; + // Permute only if num_dimensions greater than 2 + if(shape.num_dimensions() > 2) + { + perm = (data_layout == arm_compute::DataLayout::NHWC) ? arm_compute::PermutationVector(2U, 0U, 1U) : arm_compute::PermutationVector(1U, 2U, 0U); + + arm_compute::PermutationVector perm_shape = (data_layout == arm_compute::DataLayout::NCHW) ? arm_compute::PermutationVector(2U, 0U, 1U) : arm_compute::PermutationVector(1U, 2U, 0U); + arm_compute::permute(permuted_shape, perm_shape); + } + + return std::make_pair(permuted_shape, perm); +} +} // namespace + void TFPreproccessor::preprocess(ITensor &tensor) { Window window; @@ -118,8 +141,15 @@ bool PPMAccessor::access_tensor(ITensor &tensor) // Open PPM file ppm.open(_ppm_path); - ARM_COMPUTE_ERROR_ON_MSG(ppm.width() != tensor.info()->dimension(0) || ppm.height() != tensor.info()->dimension(1), - "Failed to load image file: dimensions [%d,%d] not correct, expected [%d,%d].", ppm.width(), ppm.height(), tensor.info()->dimension(0), tensor.info()->dimension(1)); + // Get permutated shape and permutation parameters + TensorShape permuted_shape = tensor.info()->tensor_shape(); + arm_compute::PermutationVector perm; + if(tensor.info()->data_layout() != DataLayout::NCHW) + { + std::tie(permuted_shape, perm) = compute_permutation_paramaters(tensor.info()->tensor_shape(), tensor.info()->data_layout()); + } + ARM_COMPUTE_ERROR_ON_MSG(ppm.width() != permuted_shape.x() || ppm.height() != permuted_shape.y(), + "Failed to load image file: dimensions [%d,%d] not correct, expected [%d,%d].", ppm.width(), ppm.height(), permuted_shape.x(), permuted_shape.y()); // Fill the tensor with the PPM content (BGR) ppm.fill_planar_tensor(tensor, _bgr); @@ -320,8 +350,8 @@ bool RandomAccessor::access_tensor(ITensor &tensor) return true; } -NumPyBinLoader::NumPyBinLoader(std::string filename) - : _filename(std::move(filename)) +NumPyBinLoader::NumPyBinLoader(std::string filename, DataLayout file_layout) + : _filename(std::move(filename)), _file_layout(file_layout) { } @@ -366,30 +396,57 @@ bool NumPyBinLoader::access_tensor(ITensor &tensor) } } + bool are_layouts_different = (_file_layout != tensor.info()->data_layout()); + // Validate tensor ranks ARM_COMPUTE_ERROR_ON_MSG(shape.size() != tensor_shape.num_dimensions(), "Tensor ranks mismatch"); + // Set permutation parameters if needed + TensorShape permuted_shape = tensor_shape; + arm_compute::PermutationVector perm; + if(are_layouts_different) + { + std::tie(permuted_shape, perm) = compute_permutation_paramaters(tensor_shape, tensor.info()->data_layout()); + } + // Validate shapes for(size_t i = 0; i < shape.size(); ++i) { - ARM_COMPUTE_ERROR_ON_MSG(tensor_shape[i] != shape[i], "Tensor dimensions mismatch"); + ARM_COMPUTE_ERROR_ON_MSG(permuted_shape[i] != shape[i], "Tensor dimensions mismatch"); } - // Read data - if(tensor.info()->padding().empty() && (dynamic_cast(&tensor) == nullptr)) + // Validate shapes and copy tensor + if(!are_layouts_different || perm.num_dimensions() <= 2) { - // If tensor has no padding read directly from stream. - stream.read(reinterpret_cast(tensor.buffer()), tensor.info()->total_size()); + // Read data + if(tensor.info()->padding().empty() && (dynamic_cast(&tensor) == nullptr)) + { + // If tensor has no padding read directly from stream. + stream.read(reinterpret_cast(tensor.buffer()), tensor.info()->total_size()); + } + else + { + // If tensor has padding accessing tensor elements through execution window. + Window window; + window.use_tensor_dimensions(tensor_shape); + + execute_window_loop(window, [&](const Coordinates & id) + { + stream.read(reinterpret_cast(tensor.ptr_to_element(id)), tensor.info()->element_size()); + }); + } } else { // If tensor has padding accessing tensor elements through execution window. Window window; - window.use_tensor_dimensions(tensor_shape); + window.use_tensor_dimensions(permuted_shape); execute_window_loop(window, [&](const Coordinates & id) { - stream.read(reinterpret_cast(tensor.ptr_to_element(id)), tensor.info()->element_size()); + Coordinates coords(id); + arm_compute::permute(coords, perm); + stream.read(reinterpret_cast(tensor.ptr_to_element(coords)), tensor.info()->element_size()); }); } return true; -- cgit v1.2.1