From 1df9f6ed4245489b74875893c695367bd0d6e3d8 Mon Sep 17 00:00:00 2001 From: Viet-Hoa Do Date: Mon, 24 Jul 2023 17:57:12 +0100 Subject: Add kernel argument emitting Resolves: COMPMID-6391 Signed-off-by: Viet-Hoa Do Change-Id: I0d54d99ffad275400c6da7fe16deb544553060eb Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/10004 Reviewed-by: Anitha Raj Reviewed-by: Gunes Bayir Tested-by: Arm Jenkins Comments-Addressed: Arm Jenkins Benchmark: Arm Jenkins --- compute_kernel_writer/CMakeLists.txt | 1 + compute_kernel_writer/include/ckw/Kernel.h | 16 +-- compute_kernel_writer/include/ckw/KernelArgument.h | 98 +++++++++++++++++++ compute_kernel_writer/src/Kernel.cpp | 9 +- compute_kernel_writer/src/KernelArgument.cpp | 67 +++++++++++++ compute_kernel_writer/src/cl/CLKernelWriter.cpp | 61 +++++++++++- compute_kernel_writer/validation/Validation.cpp | 3 + .../tests/CLKernelWriterDeclareTensorTest.h | 107 +++++++++++++++++++++ 8 files changed, 352 insertions(+), 10 deletions(-) create mode 100644 compute_kernel_writer/include/ckw/KernelArgument.h create mode 100644 compute_kernel_writer/src/KernelArgument.cpp create mode 100644 compute_kernel_writer/validation/tests/CLKernelWriterDeclareTensorTest.h (limited to 'compute_kernel_writer') diff --git a/compute_kernel_writer/CMakeLists.txt b/compute_kernel_writer/CMakeLists.txt index 8f896ef35f..ec985ca427 100644 --- a/compute_kernel_writer/CMakeLists.txt +++ b/compute_kernel_writer/CMakeLists.txt @@ -121,6 +121,7 @@ target_sources(ckw PRIVATE src/Error.cpp src/Helpers.cpp src/Kernel.cpp + src/KernelArgument.cpp src/KernelWriter.cpp src/Tensor3dMapper.cpp src/TensorInfo.cpp diff --git a/compute_kernel_writer/include/ckw/Kernel.h b/compute_kernel_writer/include/ckw/Kernel.h index d93ed6f1d3..dc0cad5503 100644 --- a/compute_kernel_writer/include/ckw/Kernel.h +++ b/compute_kernel_writer/include/ckw/Kernel.h @@ -25,7 +25,9 @@ #ifndef CKW_INCLUDE_CKW_KERNEL_H #define CKW_INCLUDE_CKW_KERNEL_H +#include "ckw/KernelArgument.h" #include +#include namespace ckw { @@ -48,22 +50,24 @@ public: /** Initialize a new instance of @ref Kernel class with all emitted kernel information. * * @param[in] language The target language of the kernel. + * @param[in] arguments The list of kernel arguments. * @param[in] source_code The source code of the kernel. */ - Kernel(TargetLanguage language, const std::string &source_code); + Kernel(TargetLanguage language, const std::vector &arguments, const std::string &source_code); /** Get the target language. */ TargetLanguage target_language() const; + /** Get the list of arguments. */ + const std::vector &arguments() const; + /** Get the source code. */ const std::string &source_code() const; - /** Add a tile operand */ - virtual TileOperand &add_operand(const std::string &name, const TileInfo &tile_info) = 0; - private: - TargetLanguage _language; - std::string _source_code; + TargetLanguage _language; + std::vector _arguments; + std::string _source_code; }; } // namespace ckw diff --git a/compute_kernel_writer/include/ckw/KernelArgument.h b/compute_kernel_writer/include/ckw/KernelArgument.h new file mode 100644 index 0000000000..530e2920eb --- /dev/null +++ b/compute_kernel_writer/include/ckw/KernelArgument.h @@ -0,0 +1,98 @@ +/* + * 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_INCLUDE_CKW_KERNELARGUMENT_H +#define CKW_INCLUDE_CKW_KERNELARGUMENT_H + +#include "ckw/types/TensorComponentType.h" +#include "ckw/types/TensorStorageType.h" +#include + +namespace ckw +{ + +/** A kernel argument which can be either a tensor storage or a tensor component. */ +class KernelArgument +{ +public: + /** The type of kernel argument. */ + enum class Type : int32_t + { + /** The argument that provides the read and/or write access to the tensor data. + * + * See @ref ckw::TensorStorageType to see the list of supported storage type. + */ + TensorStorage, + + /** The argument that provides extra information about the tensor. + * + * See @ref ckw::TensorComponentType to see the list of supported component. + */ + TensorComponent, + }; + + /** Initialize a new instance of kernel argument class for a tensor storage argument. */ + KernelArgument(int32_t tensor_id, TensorStorageType storage_type); + + /** Initialize a new instance of kernel argument class for a tensor component argument. */ + KernelArgument(int32_t tensor_id, TensorComponentType component_type); + + /** Get the type of kernel argument. */ + Type type() const; + + /** Get the argument ID. + * + * This method can be used to get the tensor info ID of both tensor storage and tensor component arguments. + */ + int32_t id() const; + + /** Get the type of tensor storage. + * + * This method can only be used for tensor storage argument. + */ + TensorStorageType tensor_storage_type() const; + + /** Get the tensor component type. + * + * This method can only be used for tensor component argument. + */ + TensorComponentType tensor_component_type() const; + +private: + Type _type; + int32_t _id; + + union SubId + { + int32_t unknown; + TensorStorageType tensor_storage_type; + TensorComponentType tensor_component_type; + }; + + SubId _sub_id{ 0 }; +}; + +} // namespace ckw + +#endif // CKW_INCLUDE_CKW_KERNELARGUMENT_H diff --git a/compute_kernel_writer/src/Kernel.cpp b/compute_kernel_writer/src/Kernel.cpp index 5eea1aa548..bfb0f46300 100644 --- a/compute_kernel_writer/src/Kernel.cpp +++ b/compute_kernel_writer/src/Kernel.cpp @@ -30,8 +30,8 @@ namespace ckw Kernel::~Kernel() = default; -Kernel::Kernel(TargetLanguage language, const std::string &source_code) - : _language(language), _source_code(source_code) +Kernel::Kernel(TargetLanguage language, const std::vector &arguments, const std::string &source_code) + : _language(language), _arguments(arguments), _source_code(source_code) { } @@ -40,6 +40,11 @@ TargetLanguage Kernel::target_language() const return _language; } +const std::vector &Kernel::arguments() const +{ + return _arguments; +} + const std::string &Kernel::source_code() const { return _source_code; diff --git a/compute_kernel_writer/src/KernelArgument.cpp b/compute_kernel_writer/src/KernelArgument.cpp new file mode 100644 index 0000000000..a31ca1757b --- /dev/null +++ b/compute_kernel_writer/src/KernelArgument.cpp @@ -0,0 +1,67 @@ +/* + * 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 "ckw/KernelArgument.h" +#include "ckw/Error.h" + +namespace ckw +{ + +KernelArgument::KernelArgument(int32_t tensor_id, TensorStorageType storage_type) + : _type(Type::TensorStorage), _id(tensor_id) +{ + _sub_id.tensor_storage_type = storage_type; +} + +KernelArgument::KernelArgument(int32_t tensor_id, TensorComponentType component_type) + : _type(Type::TensorComponent), _id(tensor_id) +{ + _sub_id.tensor_component_type = component_type; +} + +KernelArgument::Type KernelArgument::type() const +{ + return _type; +} + +int32_t KernelArgument::id() const +{ + return _id; +} + +TensorStorageType KernelArgument::tensor_storage_type() const +{ + CKW_ASSERT(_type == Type::TensorStorage); + + return _sub_id.tensor_storage_type; +} + +TensorComponentType KernelArgument::tensor_component_type() const +{ + CKW_ASSERT(_type == Type::TensorComponent); + + return _sub_id.tensor_component_type; +} + +} // namespace ckw diff --git a/compute_kernel_writer/src/cl/CLKernelWriter.cpp b/compute_kernel_writer/src/cl/CLKernelWriter.cpp index 9363076901..88ada37d71 100644 --- a/compute_kernel_writer/src/cl/CLKernelWriter.cpp +++ b/compute_kernel_writer/src/cl/CLKernelWriter.cpp @@ -26,6 +26,8 @@ #include "ckw/Error.h" #include "ckw/Kernel.h" #include "ckw/TileOperand.h" +#include "ckw/types/TargetLanguage.h" +#include "src/ITensorComponent.h" #include "src/cl/CLHelpers.h" #include "src/cl/CLTensorArgument.h" #include "src/cl/CLTile.h" @@ -39,8 +41,63 @@ CLKernelWriter::~CLKernelWriter() = default; std::unique_ptr CLKernelWriter::emit_kernel(const std::string &name) { - CKW_UNUSED(name); - CKW_THROW_MSG("Not implemented!"); + std::string code; + + code += "__kernel void "; + code += name; + code += "\n(\n"; + + // Create the list of arguments. + std::vector arguments; + + for(const auto &tensor : _tensors) + { + const auto tensor_id = tensor->info().id(); + + const auto storages = tensor->storages(); + const auto components = tensor->components(); + + for(const auto &storage : storages) + { + code += cl_get_variable_storagetype_as_string(storage.type); + code += " "; + code += storage.val; + code += ",\n"; + + arguments.emplace_back(tensor_id, storage.type); + } + + for(const auto &component : components) + { + const auto &tile = component->tile(); + const auto &tile_info = tile.info(); + + CKW_ASSERT(tile_info.height() == 1); + CKW_ASSERT(tile_info.width() == 1); + + code += cl_get_variable_datatype_as_string(tile_info.data_type(), 1); + code += " "; + code += tile.name(); + code += ",\n"; + + arguments.emplace_back(tensor_id, component->component_type()); + } + } + + if(code.size() >= 2 && code[code.size() - 2] == ',' && code[code.size() - 1] == '\n') + { + // Remove the last comma in the argument list. + code.pop_back(); + code[code.size() - 1] = '\n'; + } + + code += ")\n{\n"; + + code += _body_source_code; + + code += "}\n"; + + return std::make_unique(TargetLanguage::OpenCL, arguments, code); } void CLKernelWriter::comment(const std::string &text) diff --git a/compute_kernel_writer/validation/Validation.cpp b/compute_kernel_writer/validation/Validation.cpp index 5d53a16eff..f8ee27cee0 100644 --- a/compute_kernel_writer/validation/Validation.cpp +++ b/compute_kernel_writer/validation/Validation.cpp @@ -29,6 +29,7 @@ #include "tests/CLTileTest.hpp" #include "tests/TensorBitMaskTest.h" #include "tests/UtilsTest.h" +#include "validation/tests/CLKernelWriterDeclareTensorTest.h" #include #include @@ -73,6 +74,7 @@ int32_t main() const auto test21 = std::make_unique(); const auto test22 = std::make_unique(); const auto test23 = std::make_unique(); + const auto test24 = std::make_unique(); tests.push_back(test3.get()); tests.push_back(test4.get()); @@ -97,6 +99,7 @@ int32_t main() tests.push_back(test21.get()); tests.push_back(test22.get()); tests.push_back(test23.get()); + tests.push_back(test24.get()); #endif /* COMPUTE_KERNEL_WRITER_OPENCL_ENABLED */ bool all_test_passed = true; diff --git a/compute_kernel_writer/validation/tests/CLKernelWriterDeclareTensorTest.h b/compute_kernel_writer/validation/tests/CLKernelWriterDeclareTensorTest.h new file mode 100644 index 0000000000..3e1056972e --- /dev/null +++ b/compute_kernel_writer/validation/tests/CLKernelWriterDeclareTensorTest.h @@ -0,0 +1,107 @@ +/* + * 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_VALIDATION_TESTS_CLKERNELWRITERDECLARETENSORTEST_H +#define CKW_VALIDATION_TESTS_CLKERNELWRITERDECLARETENSORTEST_H + +#include "ckw/Error.h" +#include "ckw/Kernel.h" +#include "ckw/KernelArgument.h" +#include "ckw/TensorInfo.h" +#include "ckw/types/TensorComponentType.h" +#include "ckw/types/TensorDataLayout.h" +#include "src/cl/CLKernelWriter.h" +#include "validation/tests/common/Common.h" + +namespace ckw +{ + +class CLKernelWriterDeclareTensorTest : public ITest +{ +public: + CLKernelWriterDeclareTensorTest() + { + } + + std::string name() override + { + return "CLKernelWriterDeclareTensorTest"; + } + + bool run() override + { + auto all_tests_passed = true; + + CLKernelWriter writer; + + auto src = writer.declare_tensor_argument("src", TensorInfo(DataType::Fp32, TensorShape{ 2, 3, 4, 5 }, TensorDataLayout::Nhwc, 0)); + auto dst = writer.declare_tensor_argument("dst", TensorInfo(DataType::Fp32, TensorShape{ 6, 7, 8, 9 }, TensorDataLayout::Nhwc, 1)); + + auto src_dim0 = src.dim0(); + auto src_stride2 = src.stride2(); + auto src_offset_element = src.offset_first_element_in_bytes(); + + auto dst_dim1 = dst.dim0(); + + auto src_dim0_again = src.dim0(); + + CKW_UNUSED(src_dim0, src_stride2, src_offset_element, dst_dim1, src_dim0_again); + + const auto kernel = writer.emit_kernel("test_kernel"); + + const std::string expected_code = + "__kernel void test_kernel\n" + "(\n" + "int G0__src_dim0,\n" + "int G0__src_stride2,\n" + "int G0__src_offset_first_element,\n" + "int G0__dst_dim0\n" + ")\n" + "{\n" + "}\n"; + + const auto &actual_code = kernel->source_code(); + + int test_id = 0; + VALIDATE_TEST(kernel->arguments().size() == 4, all_tests_passed, test_id++); + test_tensor_component_argument(kernel->arguments()[0], 0, TensorComponentType::Dim0, all_tests_passed, test_id); + test_tensor_component_argument(kernel->arguments()[1], 0, TensorComponentType::Stride2, all_tests_passed, test_id); + test_tensor_component_argument(kernel->arguments()[2], 0, TensorComponentType::OffsetFirstElement, all_tests_passed, test_id); + test_tensor_component_argument(kernel->arguments()[3], 1, TensorComponentType::Dim0, all_tests_passed, test_id); + VALIDATE_TEST(actual_code == expected_code, all_tests_passed, test_id++); + + return all_tests_passed; + } + + void test_tensor_component_argument(const KernelArgument &arg, int32_t tensor_id, TensorComponentType component_type, bool &all_tests_passed, int &test_id) + { + VALIDATE_TEST(arg.type() == KernelArgument::Type::TensorComponent, all_tests_passed, test_id++); + VALIDATE_TEST(arg.id() == tensor_id, all_tests_passed, test_id++); + VALIDATE_TEST(arg.tensor_component_type() == component_type, all_tests_passed, test_id++); + } +}; + +} // namespace ckw + +#endif // CKW_VALIDATION_TESTS_CLKERNELWRITERDECLARETENSORTEST_H -- cgit v1.2.1