ONE - On-device Neural Engine
Loading...
Searching...
No Matches
PermuteLayer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef __ONERT_BACKEND_BUILTIN_KERNEL_PERMUTELAYER_H__
18#define __ONERT_BACKEND_BUILTIN_KERNEL_PERMUTELAYER_H__
19
20#include "../ExternalContext.h"
21#include "../../../exec/IPermuteFunction.h"
22
23#include <ruy/thread_pool.h> // from @ruy
24
26{
27
29{
30public:
31 PermuteLayer(const std::vector<ITensor *> &src_tensors, const std::vector<ITensor *> &dst_tensors,
32 const std::vector<ir::PermuteType> &types,
33 const std::shared_ptr<ExternalContext> &external_context);
34
35 void optimize() override;
36
37 void run() override;
38
39private:
40 std::shared_ptr<ExternalContext> _external_context;
41
42private:
43 void appendPermuteTasks(const ITensor *src_tensor, ITensor *dst_tensor,
44 const ir::Shape &loop_shape, size_t size,
45 const ir::PermuteType &permute_type);
46
47 void runPermuteTasks(backend::ITensor *src, uint8_t *dst_buffer);
48
49 struct PermuteWorkerTask : ruy::Task
50 {
51 using Strides = ir::Coordinates;
52
53 PermuteWorkerTask(const ITensor &src_tensor, ITensor &dst_tensor,
54 const ir::Coordinates &start_coords, const ir::Shape &loop_shape, size_t size,
55 const ir::PermuteType &permute_type)
56 : _src_buffer{src_tensor.buffer()}, _dst_buffer{dst_tensor.buffer()},
57 _src_start_offset{src_tensor.calcOffset(start_coords)},
58 _dst_start_offset{dst_tensor.calcOffset(start_coords)}, _src_strides{}, _dst_strides{},
59 _loop_shape{loop_shape}, _size{size}, _permute_type{permute_type}
60 {
61 // Set strides
62 setStrides(src_tensor, &_src_strides);
63 setStrides(dst_tensor, &_dst_strides);
64 }
65 // Constructor for a copy
66 PermuteWorkerTask(const uint8_t *src_buffer, uint8_t *dst_buffer, uint32_t src_start_offset,
67 uint32_t dst_start_offset, size_t size)
68 : _src_buffer{src_buffer}, _dst_buffer{dst_buffer}, _src_start_offset{src_start_offset},
69 _dst_start_offset{dst_start_offset}, _src_strides{0}, _dst_strides{0}, _loop_shape{1},
70 _size{size}, _permute_type{ir::PermuteType::SAME}
71 {
72 // DO NOTHING
73 }
74 void setBuffers(const uint8_t *src_buffer, uint8_t *dst_buffer)
75 {
76 _src_buffer = src_buffer;
77 _dst_buffer = dst_buffer;
78 }
79 void Run() override
80 {
81 ShapeLoop(_loop_shape, [&](const onert::ir::Coordinates &coords) {
82 size_t src_offset = _src_start_offset;
83 size_t dst_offset = _dst_start_offset;
84 assert(static_cast<size_t>(_loop_shape.rank()) == coords.size());
85 ir::Coordinates dst_coords = coords;
86 if (_permute_type != ir::PermuteType::SAME && _loop_shape.rank() == 4)
87 {
88 dst_coords = ir::convertCoordinates(coords, _permute_type);
89 }
90 for (auto i = 0; i < _loop_shape.rank(); ++i)
91 {
92 assert(coords[i] >= 0 && dst_coords[i] >= 0);
93 src_offset += coords[i] * _src_strides[i];
94 dst_offset += dst_coords[i] * _dst_strides[i];
95 }
96 memcpy(_dst_buffer + dst_offset, _src_buffer + src_offset, _size);
97 });
98 }
99
100 private:
101 void setStrides(const ITensor &tensor, Strides *strides)
102 {
103 auto shape = tensor.getShape();
104 const size_t rank = shape.rank();
105 for (size_t i = 0; i < rank; ++i)
106 {
107 ir::Coordinates no_step(rank), one_step(rank);
108 one_step.set(i, 1);
109 if (shape.dim(i) > 1)
110 {
111 strides->set(i, tensor.calcOffset(one_step) - tensor.calcOffset(no_step));
112 }
113 else
114 {
115 // If dimension value is 0 or 1, the stride of the dimension will be not used
116 // Do not call calcOffset() with coordinate value that is greater than dimension value
117 strides->set(i, 0);
118 }
119 assert((*strides)[i] >= 0);
120 }
121 }
122
123 private:
124 const uint8_t *_src_buffer;
125 uint8_t *_dst_buffer;
126 size_t _src_start_offset;
127 size_t _dst_start_offset;
128 Strides _src_strides;
129 Strides _dst_strides;
130 const ir::Shape _loop_shape;
131 const size_t _size;
132 const ir::PermuteType _permute_type;
133 };
134 std::unordered_map<const ITensor *, std::vector<PermuteWorkerTask>> _tasks_map;
135};
136
137} // namespace onert::backend::builtin::kernel
138
139#endif // __ONERT_BACKEND_BUILTIN_KERNEL_PERMUTELAYER_H__
Array< CornerBox > coords
Class to represent position(offset) of tensor. Assume that the front is higher dimensional....
Definition Coordinates.h:35
void set(size_t dimension, int32_t coordinate)
Set the coordinate of one of the coordinates.
Definition Coordinates.h:77
Coordinates convertCoordinates(const Coordinates &coords, const PermuteType &type)
Convert coordinate for layout change.
PermuteType
Definition Layout.h:36
int32_t size[5]
Definition Slice.cpp:35
void ShapeLoop(const onert::ir::Shape &shape, L lambda_function)
Definition Utils.h:60
CLTensor src_tensor
CLTensor dst_tensor