From bd738081b8fcea4599a06f01d5c07979f3b0fcb3 Mon Sep 17 00:00:00 2001 From: David Monahan Date: Fri, 8 Dec 2023 12:50:02 +0000 Subject: IVGCVSW-7165 - PreCompiledWorkload and Conv2d Integration work for GpuFsa * Add PreCompiledWorkload implementation for GpuFsa * Add ConstantWorkload implementation for GpuFsa * Add Input/Output workloads for GpuFsa * Added CopyMemGeneric workload for GpuFsa * Separate creation and validation of sketch tensors into seperate functions Signed-off-by: Kevin May Signed-off-by: David Monahan Change-Id: Ie7299a4c61073b5ca03d9f8681458869ef7ce743 --- src/backends/gpuFsa/layers/CMakeLists.txt | 14 ++ src/backends/gpuFsa/layers/GpuFsaConvolution2d.cpp | 180 +++++++++++++++++++++ src/backends/gpuFsa/layers/GpuFsaConvolution2d.hpp | 30 ++++ 3 files changed, 224 insertions(+) create mode 100644 src/backends/gpuFsa/layers/CMakeLists.txt create mode 100644 src/backends/gpuFsa/layers/GpuFsaConvolution2d.cpp create mode 100644 src/backends/gpuFsa/layers/GpuFsaConvolution2d.hpp (limited to 'src/backends/gpuFsa/layers') diff --git a/src/backends/gpuFsa/layers/CMakeLists.txt b/src/backends/gpuFsa/layers/CMakeLists.txt new file mode 100644 index 0000000000..3a02ce1a77 --- /dev/null +++ b/src/backends/gpuFsa/layers/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright © 2023-2024 Arm Ltd and Contributors. All rights reserved. +# SPDX-License-Identifier: MIT +# + +list(APPEND armnnGpuFsaBackendLayerValidators_sources + GpuFsaConvolution2d.cpp + GpuFsaConvolution2d.hpp + ) + +add_library(armnnGpuFsaBackendLayerValidators OBJECT ${armnnGpuFsaBackendLayerValidators_sources}) +target_include_directories(armnnGpuFsaBackendLayerValidators PRIVATE ${PROJECT_SOURCE_DIR}/src/armnn) +target_include_directories(armnnGpuFsaBackendLayerValidators PRIVATE ${PROJECT_SOURCE_DIR}/src/armnnUtils) +target_include_directories(armnnGpuFsaBackendLayerValidators PRIVATE ${PROJECT_SOURCE_DIR}/src/backends) diff --git a/src/backends/gpuFsa/layers/GpuFsaConvolution2d.cpp b/src/backends/gpuFsa/layers/GpuFsaConvolution2d.cpp new file mode 100644 index 0000000000..c7137d7ac8 --- /dev/null +++ b/src/backends/gpuFsa/layers/GpuFsaConvolution2d.cpp @@ -0,0 +1,180 @@ +// +// Copyright © 2024 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "GpuFsaConvolution2d.hpp" + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace armnn +{ + +using namespace armcomputetensorutils; + +arm_compute::Status GpuFsaConvolution2dValidate(const TensorInfo& input, + const Convolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases) +{ + // Create a new workload sketch, for validation purposes + auto compileCtx = arm_compute::CLKernelLibrary::get().get_compile_context(); + auto workloadContext = GpuWorkloadContext(&compileCtx); + GpuWorkloadSketch sketch{ &workloadContext }; + + // Build and create tensor infos using the sketch + const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout); + arm_compute::TensorInfo aclWeightsInfo = BuildArmComputeTensorInfo(weights, descriptor.m_DataLayout); + aclWeightsInfo.set_are_values_constant(weights.IsConstant()); + + auto inputInfo = workloadContext.create_tensor_info(aclInputInfo); + auto weightInfo = workloadContext.create_tensor_info(aclWeightsInfo); + + // Only create the bias tensor info if enabled, otherwise pass nullptr to validate_op + arm_compute::TensorInfo aclBiasInfo; + arm_compute::TensorInfo biasSketchInfo; + arm_compute::TensorInfo* biasSketchInfoPtr = nullptr; + + if (descriptor.m_BiasEnabled) + { + if(!biases.has_value()) + { + throw InvalidArgumentException("GpuFsaConvolution2d::ValidateOp: No biases set when biases are enabled"); + } + aclBiasInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout); + aclBiasInfo.set_are_values_constant(biases.value().IsConstant()); + + biasSketchInfo = workloadContext.create_tensor_info(aclBiasInfo); + biasSketchInfoPtr = &biasSketchInfo; + } + + // Set Conv2d attributes using descriptor + const arm_compute::Size2D aclDilationInfo = BuildArmComputeSize2D(descriptor.m_DilationX, + descriptor.m_DilationY); + const arm_compute::Padding2D aclPadInfo = BuildArmComputePaddingInfo(descriptor); + const arm_compute::Size2D aclStrideInfo = BuildArmComputeSize2D(descriptor.m_StrideX, descriptor.m_StrideY); + + Conv2dAttributes conv2DAttributes{}; + conv2DAttributes.dilation(aclDilationInfo); + conv2DAttributes.pad(aclPadInfo); + conv2DAttributes.stride(aclStrideInfo); + + // Validate operator, check status and update reasonIfUnsupported + arm_compute::Status aclStatus = GpuConv2d::validate_op(sketch, + &inputInfo, + &weightInfo, + biasSketchInfoPtr, + conv2DAttributes); + + return aclStatus; +} + +void GpuFsaConvolution2dCreateOp(GpuFsaPreCompiledBlob* blob, + const TensorInfo& input, + const Convolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases) +{ +/* + * Creating an Op for the GpuFds backend requires us to create and maintain quite a bit of data, which is then stored + * in a GpuFsaPreCompiledBlob for execution later. Specifically we need: + * GpuWorkloadContext, this contains the TensorInfos and is unique to the Graph being executed + * Sketch, this is similar to a subgraph and can contain one or more operations. Multiple ops can be "fused" together + * using a single sketch. + * The TensorInfoIds, these are the ids of the TensorInfos used when creating the sketch. They refer to the TensorInfos + * stored within the GpuWorkloadContext and are used to fetch them later when executing the sketch. + */ + using namespace arm_compute::experimental::dynamic_fusion; + GpuWorkloadSketch* sketch = blob->sketch.get(); + GpuWorkloadContext* workloadContext = blob->workloadContext.get(); + std::vector inputIds = {}; + std::vector outputIds = {}; + + // Build and create tensor infos using the sketch + const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout); + arm_compute::TensorInfo aclWeightsInfo = BuildArmComputeTensorInfo(weights, descriptor.m_DataLayout); + aclWeightsInfo.set_are_values_constant(weights.IsConstant()); + auto inputInfo = workloadContext->create_tensor_info(aclInputInfo); + aclWeightsInfo.set_are_values_constant(weights.IsConstant()); + inputIds.emplace_back(inputInfo.id()); + + auto weightInfo = workloadContext->create_tensor_info(aclWeightsInfo); + inputIds.emplace_back(weightInfo.id()); + + // Only create the bias tensor info if enabled, otherwise pass nullptr to validate_op + arm_compute::TensorInfo aclBiasInfo; + arm_compute::TensorInfo biasSketchInfo; + arm_compute::ITensorInfo* biasSketchInfoPtr = nullptr; + + if (descriptor.m_BiasEnabled) + { + if(!biases.has_value()) + { + throw InvalidArgumentException("GpuFsaConvolution2d::CreateOp: No biases set when biases are enabled"); + } + aclBiasInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout); + aclBiasInfo.set_are_values_constant(biases.value().IsConstant()); + + biasSketchInfo = workloadContext->create_tensor_info(aclBiasInfo); + inputIds.emplace_back(biasSketchInfo.id()); + biasSketchInfoPtr = workloadContext->implementation().get_tensor_info(biasSketchInfo.id()); + } + + // Set Conv2d attributes using descriptor + const arm_compute::Size2D aclDilationInfo = BuildArmComputeSize2D(descriptor.m_DilationX, + descriptor.m_DilationY); + const arm_compute::Padding2D aclPadInfo = BuildArmComputePaddingInfo(descriptor); + const arm_compute::Size2D aclStrideInfo = BuildArmComputeSize2D(descriptor.m_StrideX, descriptor.m_StrideY); + + Conv2dAttributes conv2DAttributes{}; + conv2DAttributes.dilation(aclDilationInfo); + conv2DAttributes.pad(aclPadInfo); + conv2DAttributes.stride(aclStrideInfo); + + // Validate operator, check status and update reasonIfUnsupported + arm_compute::Status aclStatus = + GpuConv2d::validate_op(*sketch, + workloadContext->implementation().get_tensor_info(inputInfo.id()), + workloadContext->implementation().get_tensor_info(weightInfo.id()), + biasSketchInfoPtr, + conv2DAttributes); + + const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK); + if (!supported) + { + throw BackendCapabilityException("\"GpuFsa\" backend failed during Convolution2D operation validation"); + } + + arm_compute::ITensorInfo* convOutInfo = + GpuConv2d::create_op(*sketch, + workloadContext->implementation().get_tensor_info(inputInfo.id()), + workloadContext->implementation().get_tensor_info(weightInfo.id()), + biasSketchInfoPtr, + conv2DAttributes); + + arm_compute::TensorInfo outputDstInfo = workloadContext->create_tensor_info(); + outputIds.emplace_back(outputDstInfo.id()); + + GpuOutput::create_op(*sketch, convOutInfo, workloadContext->implementation().get_tensor_info(outputDstInfo.id())); + blob->inputIds = std::make_unique>(inputIds); + blob->outputIds = std::make_unique>(outputIds); +} + +} // namespace armnn diff --git a/src/backends/gpuFsa/layers/GpuFsaConvolution2d.hpp b/src/backends/gpuFsa/layers/GpuFsaConvolution2d.hpp new file mode 100644 index 0000000000..3346dc1028 --- /dev/null +++ b/src/backends/gpuFsa/layers/GpuFsaConvolution2d.hpp @@ -0,0 +1,30 @@ +// +// Copyright © 2023-2024 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include +#include + +#include +#include +#include + +namespace armnn +{ + +using namespace arm_compute::experimental::dynamic_fusion; + +arm_compute::Status GpuFsaConvolution2dValidate(const TensorInfo& input, + const Convolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases); + +void GpuFsaConvolution2dCreateOp(GpuFsaPreCompiledBlob* blob, + const TensorInfo& input, + const Convolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases); + +} // namespace armnn -- cgit v1.2.1