From 2a07e184f7b359d13aa6cacfdc6431f9b191ef0c Mon Sep 17 00:00:00 2001 From: Anthony Barbier Date: Fri, 4 Aug 2017 18:20:27 +0100 Subject: COMPMID-363 Add Graph library support Change-Id: Ie841419bf65d0e06bdfe0bdd2d8d4e0bb3631e54 Reviewed-on: http://mpd-gerrit.cambridge.arm.com/87931 Reviewed-by: Pablo Tello Tested-by: Kaizen --- utils/GraphUtils.cpp | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 utils/GraphUtils.cpp (limited to 'utils/GraphUtils.cpp') diff --git a/utils/GraphUtils.cpp b/utils/GraphUtils.cpp new file mode 100644 index 0000000000..d763606867 --- /dev/null +++ b/utils/GraphUtils.cpp @@ -0,0 +1,165 @@ +/* + * 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 "utils/GraphUtils.h" +#include "utils/Utils.h" + +#ifdef ARM_COMPUTE_CL +#include "arm_compute/core/CL/OpenCL.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#endif /* ARM_COMPUTE_CL */ + +#include "arm_compute/core/Error.h" +#include "libnpy/npy.hpp" + +#include + +using namespace arm_compute::graph_utils; + +PPMWriter::PPMWriter(std::string name, unsigned int maximum) + : _name(std::move(name)), _iterator(0), _maximum(maximum) +{ +} + +bool PPMWriter::access_tensor(ITensor &tensor) +{ + std::stringstream ss; + ss << _name << _iterator << ".ppm"; + if(dynamic_cast(&tensor) != nullptr) + { + arm_compute::utils::save_to_ppm(dynamic_cast(tensor), ss.str()); + } +#ifdef ARM_COMPUTE_CL + else if(dynamic_cast(&tensor) != nullptr) + { + arm_compute::utils::save_to_ppm(dynamic_cast(tensor), ss.str()); + } +#endif /* ARM_COMPUTE_CL */ + + _iterator++; + if(_maximum == 0) + { + return true; + } + return _iterator < _maximum; +} + +DummyAccessor::DummyAccessor(unsigned int maximum) + : _iterator(0), _maximum(maximum) +{ +} + +bool DummyAccessor::access_tensor(ITensor &tensor) +{ + ARM_COMPUTE_UNUSED(tensor); + bool ret = _maximum == 0 || _iterator < _maximum; + if(_iterator == _maximum) + { + _iterator = 0; + } + else + { + _iterator++; + } + return ret; +} + +NumPyBinLoader::NumPyBinLoader(std::string filename) + : _filename(std::move(filename)) +{ +} + +bool NumPyBinLoader::access_tensor(ITensor &tensor) +{ + const TensorShape tensor_shape = tensor.info()->tensor_shape(); + std::vector shape; + + // Open file + std::ifstream stream(_filename, std::ios::in | std::ios::binary); + ARM_COMPUTE_ERROR_ON_MSG(!stream.good(), "Failed to load binary data"); + // Check magic bytes and version number + unsigned char v_major = 0; + unsigned char v_minor = 0; + npy::read_magic(stream, &v_major, &v_minor); + + // Read header + std::string header; + if(v_major == 1 && v_minor == 0) + { + header = npy::read_header_1_0(stream); + } + else if(v_major == 2 && v_minor == 0) + { + header = npy::read_header_2_0(stream); + } + else + { + ARM_COMPUTE_ERROR("Unsupported file format version"); + } + + // Parse header + bool fortran_order = false; + std::string typestr; + npy::ParseHeader(header, typestr, &fortran_order, shape); + + // Check if the typestring matches the given one + std::string expect_typestr = arm_compute::utils::get_typestring(tensor.info()->data_type()); + ARM_COMPUTE_ERROR_ON_MSG(typestr != expect_typestr, "Typestrings mismatch"); + + // Validate tensor shape + ARM_COMPUTE_ERROR_ON_MSG(shape.size() != tensor_shape.num_dimensions(), "Tensor ranks mismatch"); + if(fortran_order) + { + for(size_t i = 0; i < shape.size(); ++i) + { + ARM_COMPUTE_ERROR_ON_MSG(tensor_shape[i] != shape[i], "Tensor dimensions mismatch"); + } + } + else + { + for(size_t i = 0; i < shape.size(); ++i) + { + ARM_COMPUTE_ERROR_ON_MSG(tensor_shape[i] != shape[shape.size() - i - 1], "Tensor dimensions mismatch"); + } + } + + // Read data + if(tensor.info()->padding().empty()) + { + // 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()); + }); + } + return true; +} -- cgit v1.2.1