From 0b23e0e6402cb18ddf621d36454cadbb73959518 Mon Sep 17 00:00:00 2001 From: Viet-Hoa Do Date: Tue, 25 Jul 2023 14:00:46 +0100 Subject: Add TensorOperand and declare tensor argument Partially resolves: COMPMID-6391 Signed-off-by: Viet-Hoa Do Change-Id: I849d486401f99a93919015f2e173559dca5bffa2 Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/9972 Tested-by: Arm Jenkins Reviewed-by: Gunes Bayir Reviewed-by: Gian Marco Iodice Comments-Addressed: Arm Jenkins Benchmark: Arm Jenkins --- compute_kernel_writer/src/cl/CLKernelWriter.cpp | 14 ++ compute_kernel_writer/src/cl/CLKernelWriter.h | 13 +- compute_kernel_writer/src/cl/CLTensorArgument.cpp | 150 ++++++++------------- compute_kernel_writer/src/cl/CLTensorArgument.h | 40 ++++-- compute_kernel_writer/src/cl/CLTensorComponent.cpp | 123 +++++++++++++++++ compute_kernel_writer/src/cl/CLTensorComponent.h | 80 +++++++++++ 6 files changed, 314 insertions(+), 106 deletions(-) create mode 100644 compute_kernel_writer/src/cl/CLTensorComponent.cpp create mode 100644 compute_kernel_writer/src/cl/CLTensorComponent.h (limited to 'compute_kernel_writer/src/cl') diff --git a/compute_kernel_writer/src/cl/CLKernelWriter.cpp b/compute_kernel_writer/src/cl/CLKernelWriter.cpp index bc056c67a2..69b5244aa2 100644 --- a/compute_kernel_writer/src/cl/CLKernelWriter.cpp +++ b/compute_kernel_writer/src/cl/CLKernelWriter.cpp @@ -24,8 +24,10 @@ #include "src/cl/CLKernelWriter.h" #include "ckw/Error.h" +#include "ckw/Kernel.h" #include "ckw/TileOperand.h" #include "src/cl/CLHelpers.h" +#include "src/cl/CLTensorArgument.h" #include "src/cl/CLTile.h" #include @@ -62,6 +64,18 @@ const std::string &CLKernelWriter::body_source_code() const return _body_source_code; } +TensorOperand CLKernelWriter::declare_tensor_argument(const std::string &name, const TensorInfo &info) +{ + const auto fullname = generate_full_name(name); + + auto tensor = std::make_unique(fullname, info, false /* return_dims_by_value */); + const auto operand = create_tensor_operand(*tensor); + + _tensors.insert(std::move(tensor)); + + return operand; +} + TileOperand CLKernelWriter::declare_tile(const std::string &name, const TileInfo &tile_info) { const std::string fullname = generate_full_name(name); diff --git a/compute_kernel_writer/src/cl/CLKernelWriter.h b/compute_kernel_writer/src/cl/CLKernelWriter.h index c69a0bc07e..42d2b07ded 100644 --- a/compute_kernel_writer/src/cl/CLKernelWriter.h +++ b/compute_kernel_writer/src/cl/CLKernelWriter.h @@ -26,7 +26,6 @@ #define CKW_SRC_CL_CLKERNELWRITER_H #include "ckw/KernelWriter.h" -#include "src/cl/CLTile.h" #include #include @@ -35,6 +34,9 @@ namespace ckw { +class CLTile; +class CLTensorArgument; + /** OpenCL kernel writer. */ class CLKernelWriter : public KernelWriter { @@ -61,6 +63,12 @@ public: std::unique_ptr emit_kernel(const std::string &name) override; + // ============================================================================================= + // Tensor and tile declaration + // ============================================================================================= + + TensorOperand declare_tensor_argument(const std::string &name, const TensorInfo &info) override; + /** Declare a tile given name and tile information * * Similar to @ref KernelWriter::declare_tile() @@ -95,7 +103,8 @@ private: */ std::string _body_source_code{}; - std::set> _tiles{}; + std::set> _tensors{}; + std::set> _tiles{}; }; } // namespace ckw diff --git a/compute_kernel_writer/src/cl/CLTensorArgument.cpp b/compute_kernel_writer/src/cl/CLTensorArgument.cpp index ed1c5bd687..7d4dc958df 100644 --- a/compute_kernel_writer/src/cl/CLTensorArgument.cpp +++ b/compute_kernel_writer/src/cl/CLTensorArgument.cpp @@ -24,7 +24,10 @@ #include "src/cl/CLTensorArgument.h" #include "ckw/Error.h" +#include "src/ITensorArgument.h" +#include "src/ITensorComponent.h" #include "src/cl/CLHelpers.h" +#include "src/cl/CLTensorComponent.h" #include "src/types/TensorComponentType.h" #include @@ -39,8 +42,25 @@ CLTensorArgument::CLTensorArgument(const std::string &name, const TensorInfo &in _info = info; } -TileVariable CLTensorArgument::component(TensorComponentType x) +CLTensorArgument::~CLTensorArgument() = default; + +CLTensorComponent &CLTensorArgument::cl_component(TensorComponentType x) { + // Return the component if it has already been created. + { + const auto it = std::find_if( + _components_used.begin(), _components_used.end(), + [=](const std::unique_ptr &item) + { + return item->component_type() == x; + }); + + if(it != _components_used.end()) + { + return **it; + } + } + if(_return_dims_by_value) { uint32_t component_type = static_cast(x); @@ -100,42 +120,47 @@ TileVariable CLTensorArgument::component(TensorComponentType x) if(idx != kDynamicTensorDimensionValue) { - TileVariable t; - t.str = std::to_string(idx); - t.desc.dt = DataType::Uint32; - t.desc.len = 1; - return t; + _components_used.emplace_back(std::make_unique(*this, x, idx)); + + return *_components_used.back(); } } } - auto it = std::find(_components_used.begin(), _components_used.end(), x); + _components_used.emplace_back(std::make_unique(*this, x)); - // Add to the list of used components if not present yet - if(it == _components_used.end()) - { - _components_used.push_back(x); - } + return *_components_used.back(); +} - TileVariable t; - t.str = create_component_name(x); - t.desc.dt = DataType::Int32; - t.desc.len = 1; - return t; +ITile &CLTensorArgument::component(TensorComponentType x) +{ + return cl_component(x); } -TensorStorageVariable CLTensorArgument::storage(TensorStorageType x) +TensorStorageVariable &CLTensorArgument::storage(TensorStorageType x) { - if(std::find(_storages_used.begin(), _storages_used.end(), x) == _storages_used.end()) + // Return the storage if it has already been created. { - _storages_used.push_back(x); + const auto it = std::find_if( + _storages_used.begin(), _storages_used.end(), + [=](const TensorStorageVariable &item) + { + return item.type == x; + }); + + if(it != _storages_used.end()) + { + return *it; + } } TensorStorageVariable t; t.val = create_storage_name(x); - t.type = cl_get_variable_storagetype_as_string(x); + t.type = x; + + _storages_used.emplace_back(t); - return t; + return _storages_used.back(); } std::string CLTensorArgument::create_storage_name(TensorStorageType x) const @@ -159,87 +184,26 @@ std::string CLTensorArgument::create_storage_name(TensorStorageType x) const return var_name; } -std::string CLTensorArgument::create_component_name(TensorComponentType x) const -{ - std::string var_name = _basename; - - switch(x) - { - case TensorComponentType::OffsetFirstElement: - var_name += "_offset_first_element"; - break; - case TensorComponentType::Stride0: - var_name += "_stride0"; - break; - case TensorComponentType::Stride1: - var_name += "_stride1"; - break; - case TensorComponentType::Stride2: - var_name += "_stride2"; - break; - case TensorComponentType::Stride3: - var_name += "_stride3"; - break; - case TensorComponentType::Stride4: - var_name += "_stride4"; - break; - case TensorComponentType::Dim0: - var_name += "_dim0"; - break; - case TensorComponentType::Dim1: - var_name += "_dim1"; - break; - case TensorComponentType::Dim2: - var_name += "_dim2"; - break; - case TensorComponentType::Dim3: - var_name += "_dim3"; - break; - case TensorComponentType::Dim4: - var_name += "_dim4"; - break; - case TensorComponentType::Dim1xDim2: - var_name += "_dim1xdim2"; - break; - case TensorComponentType::Dim2xDim3: - var_name += "_dim2xdim3"; - break; - case TensorComponentType::Dim1xDim2xDim3: - var_name += "_dim1xdim2xdim3"; - break; - default: - COMPUTE_KERNEL_WRITER_ERROR_ON_MSG("Unsupported tensor component"); - return ""; - } - - return var_name; -} - std::vector CLTensorArgument::storages() const { std::vector storages; - for(auto &val : _storages_used) - { - TensorStorageVariable t; - t.val = create_storage_name(val); - t.type = cl_get_variable_storagetype_as_string(val); - storages.push_back(t); - } + storages.reserve(_storages_used.size()); + + std::copy(_storages_used.begin(), _storages_used.end(), std::back_inserter(storages)); return storages; } -std::vector CLTensorArgument::components() const +std::vector CLTensorArgument::components() const { - std::vector components; + std::vector components; - for(auto &val : _components_used) + for(const auto &component : _components_used) { - TileVariable t; - t.str = create_component_name(val); - t.desc.dt = DataType::Int32; - t.desc.len = 1; - components.push_back(t); + if(component->is_assignable()) + { + components.push_back(component.get()); + } } return components; diff --git a/compute_kernel_writer/src/cl/CLTensorArgument.h b/compute_kernel_writer/src/cl/CLTensorArgument.h index cd924846c5..4cbbee21ee 100644 --- a/compute_kernel_writer/src/cl/CLTensorArgument.h +++ b/compute_kernel_writer/src/cl/CLTensorArgument.h @@ -24,8 +24,10 @@ #ifndef CKW_SRC_CL_CLTENSORARGUMENT_H #define CKW_SRC_CL_CLTENSORARGUMENT_H -#include "src/ITensorArgument.h" - +#include "ckw/types/TensorComponentType.h" +#include "ckw/types/TensorStorageType.h" +#include "src/ITensor.h" +#include #include #include @@ -34,12 +36,16 @@ namespace ckw // Forward declarations class TensorInfo; +class ITensorComponent; +class CLTensorComponent; +class CLTensorStorage; + /** OpenCL specific tensor argument * Internally, the object keeps track of the components and storages used to minimize the number * of kernel arguments required. Therefore, if we create this object but we do not access any components * or storages, the storages() and components() method will return an empty list. */ -class CLTensorArgument : public ITensorArgument, ITensorStorageArgument, ITensorComponentArgument +class CLTensorArgument : public ITensor { public: /** Constructor @@ -51,20 +57,32 @@ public: */ CLTensorArgument(const std::string &name, const TensorInfo &info, bool return_dims_by_value); + /** Destructor. */ + ~CLTensorArgument(); + + /** Get a tensor component of the given type. + * + * This function is for internal use as it returns a reference to @ref CLTensorComponent object. + * It provides rich functionalities and doesn't require unnecessary casting + * unlike @ref CLTensorComponent::component which is for the public API and only returns + * a reference to a generic @ref ITile object. + */ + CLTensorComponent& cl_component(TensorComponentType component_type); + // Inherited method overridden - TensorStorageVariable storage(TensorStorageType x); - TileVariable component(TensorComponentType x); - std::vector storages() const; - std::vector components() const; + TensorStorageVariable &storage(TensorStorageType x) override; + ITile &component(TensorComponentType x) override; + std::vector storages() const override; + std::vector components() const override; private: std::string create_storage_name(TensorStorageType x) const; - std::string create_component_name(TensorComponentType x) const; - bool _return_dims_by_value{ false }; - std::vector _storages_used{}; - std::vector _components_used{}; + bool _return_dims_by_value{ false }; + std::vector _storages_used{}; + std::vector> _components_used{}; }; + } // namespace ckw #endif // CKW_SRC_CL_CLTENSORARGUMENT_H diff --git a/compute_kernel_writer/src/cl/CLTensorComponent.cpp b/compute_kernel_writer/src/cl/CLTensorComponent.cpp new file mode 100644 index 0000000000..c29b307748 --- /dev/null +++ b/compute_kernel_writer/src/cl/CLTensorComponent.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2023 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 "src/cl/CLTensorComponent.h" +#include "ckw/Error.h" +#include "ckw/types/TensorComponentType.h" +#include "src/cl/CLTensorArgument.h" +#include "src/cl/CLTile.h" + +namespace ckw +{ + +namespace +{ + +std::string create_component_name(const std::string &name, TensorComponentType x) +{ + std::string var_name(name); + + switch(x) + { + case TensorComponentType::OffsetFirstElement: + var_name += "_offset_first_element"; + break; + case TensorComponentType::Stride0: + var_name += "_stride0"; + break; + case TensorComponentType::Stride1: + var_name += "_stride1"; + break; + case TensorComponentType::Stride2: + var_name += "_stride2"; + break; + case TensorComponentType::Stride3: + var_name += "_stride3"; + break; + case TensorComponentType::Stride4: + var_name += "_stride4"; + break; + case TensorComponentType::Dim0: + var_name += "_dim0"; + break; + case TensorComponentType::Dim1: + var_name += "_dim1"; + break; + case TensorComponentType::Dim2: + var_name += "_dim2"; + break; + case TensorComponentType::Dim3: + var_name += "_dim3"; + break; + case TensorComponentType::Dim4: + var_name += "_dim4"; + break; + case TensorComponentType::Dim1xDim2: + var_name += "_dim1xdim2"; + break; + case TensorComponentType::Dim2xDim3: + var_name += "_dim2xdim3"; + break; + case TensorComponentType::Dim1xDim2xDim3: + var_name += "_dim1xdim2xdim3"; + break; + default: + CKW_THROW_MSG("Unsupported tensor component"); + return ""; + } + + return var_name; +} + +} // namespace + +CLTensorComponent::CLTensorComponent(const CLTensorArgument &tensor, TensorComponentType component_type) + : CLTile(create_component_name(tensor.name(), component_type), TileInfo(DataType::Int32)), _component_type(component_type) +{ +} + +CLTensorComponent::CLTensorComponent(const CLTensorArgument &tensor, TensorComponentType component_type, int32_t value) + : CLTile({ { std::to_string(value) } }, DataType::Int32), _component_type(component_type) +{ + CKW_UNUSED(tensor); +} + +CLTensorComponent::~CLTensorComponent() = default; + +ITile &CLTensorComponent::tile() +{ + return *this; +} + +const ITile &CLTensorComponent::tile() const +{ + return *this; +} + +TensorComponentType CLTensorComponent::component_type() const +{ + return _component_type; +} + +} // namespace ckw diff --git a/compute_kernel_writer/src/cl/CLTensorComponent.h b/compute_kernel_writer/src/cl/CLTensorComponent.h new file mode 100644 index 0000000000..42a42666dc --- /dev/null +++ b/compute_kernel_writer/src/cl/CLTensorComponent.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef CKW_SRC_CL_CLTENSORCOMPONENT_H +#define CKW_SRC_CL_CLTENSORCOMPONENT_H + +#include "ckw/types/TensorComponentType.h" +#include "src/ITensorComponent.h" +#include "src/cl/CLTile.h" + +namespace ckw +{ + +class CLTensorArgument; + +/** A tensor component object that can be used as a tile. + * + * The tensor component is created by @ref CLTensorArgument object when it is used + * either by the user or internally by a kernel writer operation. + * It allows the user to perform operation on tensor component just like any other tile. + * + * Because of the nature of tensor component, it's always a scalar tile of 32-bit integer. + * + * To find the list of all tensor components, see @ref TensorComponentType. + */ +class CLTensorComponent : public CLTile, public ITensorComponent +{ +public: + /** Initialize a new instance of @ref CLTensorComponent class for dynamic component. + * + * @param[in] tensor The tensor to which this component belongs. + * @param[in] component_type The tensor component type. + */ + CLTensorComponent(const CLTensorArgument &tensor, TensorComponentType component_type); + + /** Initialize a new instance of @ref CLTensorComponent class for compile-time constant component. + * + * @param[in] tensor The tensor to which this component belongs. + * @param[in] component_type The tensor component type. + * @param[in] value The value of the component. + */ + CLTensorComponent(const CLTensorArgument &tensor, TensorComponentType component_type, int32_t value); + + /** Destructor. */ + virtual ~CLTensorComponent(); + + ITile &tile() override; + + const ITile &tile() const override; + + TensorComponentType component_type() const override; + +private: + TensorComponentType _component_type{ TensorComponentType::Unknown }; +}; + +} // namespace ckw + +#endif // CKW_SRC_CL_CLTENSORCOMPONENT_H -- cgit v1.2.1