1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6
7 #include <Half.hpp>
8
9 #include <aclCommon/ArmComputeTensorUtils.hpp>
10 #include <cl/OpenClTimer.hpp>
11 #include <backendsCommon/CpuTensorHandle.hpp>
12
13 #include <armnn/Utils.hpp>
14
15 #include <arm_compute/runtime/CL/CLTensor.h>
16 #include <arm_compute/runtime/IFunction.h>
17
18 #include <sstream>
19
20 #define ARMNN_SCOPED_PROFILING_EVENT_CL(name) \
21 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(armnn::Compute::GpuAcc, \
22 name, \
23 armnn::OpenClTimer(), \
24 armnn::WallClockTimer())
25
26 namespace armnn
27 {
28
29 template <typename T>
CopyArmComputeClTensorData(arm_compute::CLTensor & dstTensor,const T * srcData)30 void CopyArmComputeClTensorData(arm_compute::CLTensor& dstTensor, const T* srcData)
31 {
32 {
33 ARMNN_SCOPED_PROFILING_EVENT_CL("MapClTensorForWriting");
34 dstTensor.map(true);
35 }
36
37 {
38 ARMNN_SCOPED_PROFILING_EVENT_CL("CopyToClTensor");
39 armcomputetensorutils::CopyArmComputeITensorData<T>(srcData, dstTensor);
40 }
41
42 dstTensor.unmap();
43 }
44
SetClStridedSliceData(const std::vector<int> & m_begin,const std::vector<int> & m_end,const std::vector<int> & m_stride)45 inline auto SetClStridedSliceData(const std::vector<int>& m_begin,
46 const std::vector<int>& m_end,
47 const std::vector<int>& m_stride)
48 {
49 arm_compute::Coordinates starts;
50 arm_compute::Coordinates ends;
51 arm_compute::Coordinates strides;
52
53 unsigned int num_dims = static_cast<unsigned int>(m_begin.size());
54
55 for (unsigned int i = 0; i < num_dims; i++) {
56 unsigned int revertedIndex = num_dims - i - 1;
57
58 starts.set(i, static_cast<int>(m_begin[revertedIndex]));
59 ends.set(i, static_cast<int>(m_end[revertedIndex]));
60 strides.set(i, static_cast<int>(m_stride[revertedIndex]));
61 }
62
63 return std::make_tuple(starts, ends, strides);
64 }
65
SetClSliceData(const std::vector<unsigned int> & m_begin,const std::vector<unsigned int> & m_size)66 inline auto SetClSliceData(const std::vector<unsigned int>& m_begin,
67 const std::vector<unsigned int>& m_size)
68 {
69 // This function must translate the size vector given to an end vector
70 // expected by the ACL NESlice workload
71 arm_compute::Coordinates starts;
72 arm_compute::Coordinates ends;
73
74 unsigned int num_dims = static_cast<unsigned int>(m_begin.size());
75
76 // For strided slices, we have the relationship size = (end - begin) / stride
77 // For slice, we assume stride to be a vector of all ones, yielding the formula
78 // size = (end - begin) therefore we know end = size + begin
79 for (unsigned int i = 0; i < num_dims; i++)
80 {
81 unsigned int revertedIndex = num_dims - i - 1;
82
83 starts.set(i, static_cast<int>(m_begin[revertedIndex]));
84 ends.set(i, static_cast<int>(m_begin[revertedIndex] + m_size[revertedIndex]));
85 }
86
87 return std::make_tuple(starts, ends);
88 }
89
InitializeArmComputeClTensorData(arm_compute::CLTensor & clTensor,const ConstCpuTensorHandle * handle)90 inline void InitializeArmComputeClTensorData(arm_compute::CLTensor& clTensor,
91 const ConstCpuTensorHandle* handle)
92 {
93 ARMNN_ASSERT(handle);
94
95 armcomputetensorutils::InitialiseArmComputeTensorEmpty(clTensor);
96 switch(handle->GetTensorInfo().GetDataType())
97 {
98 case DataType::Float16:
99 CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<armnn::Half>());
100 break;
101 case DataType::Float32:
102 CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<float>());
103 break;
104 case DataType::QAsymmU8:
105 CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<uint8_t>());
106 break;
107 ARMNN_NO_DEPRECATE_WARN_BEGIN
108 case DataType::QuantizedSymm8PerAxis:
109 ARMNN_FALLTHROUGH;
110 case DataType::QAsymmS8:
111 case DataType::QSymmS8:
112 CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int8_t>());
113 break;
114 case DataType::QSymmS16:
115 CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int16_t>());
116 break;
117 ARMNN_NO_DEPRECATE_WARN_END
118 case DataType::Signed32:
119 CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int32_t>());
120 break;
121 default:
122 ARMNN_ASSERT_MSG(false, "Unexpected tensor type.");
123 }
124 };
125
WrapClError(const cl::Error & clError,const CheckLocation & location)126 inline RuntimeException WrapClError(const cl::Error& clError, const CheckLocation& location)
127 {
128 std::stringstream message;
129 message << "CL error: " << clError.what() << ". Error code: " << clError.err();
130
131 return RuntimeException(message.str(), location);
132 }
133
RunClFunction(arm_compute::IFunction & function,const CheckLocation & location)134 inline void RunClFunction(arm_compute::IFunction& function, const CheckLocation& location)
135 {
136 try
137 {
138 function.run();
139 }
140 catch (cl::Error& error)
141 {
142 throw WrapClError(error, location);
143 }
144 }
145
146 } //namespace armnn
147