1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/lite/delegates/gpu/common/memory_management/internal.h"
17
18 #include <algorithm>
19 #include <cstddef>
20 #include <vector>
21
22 #include "tensorflow/lite/delegates/gpu/common/memory_management/types.h"
23 #include "tensorflow/lite/delegates/gpu/common/types.h"
24
25 namespace tflite {
26 namespace gpu {
27
CompareBySize(const TensorUsageWithIndex<size_t> & first,const TensorUsageWithIndex<size_t> & second)28 bool CompareBySize(const TensorUsageWithIndex<size_t>& first,
29 const TensorUsageWithIndex<size_t>& second) {
30 return first.usage_record->tensor_size > second.usage_record->tensor_size;
31 }
32
IsCoveringObject(const uint2 & first_object,const uint2 & second_object)33 bool IsCoveringObject(const uint2& first_object, const uint2& second_object) {
34 return first_object.x >= second_object.x && first_object.y >= second_object.y;
35 }
36
IsCoveringObject(const uint3 & first_object,const uint3 & second_object)37 bool IsCoveringObject(const uint3& first_object, const uint3& second_object) {
38 return first_object.x >= second_object.x &&
39 first_object.y >= second_object.y && first_object.z >= second_object.z;
40 }
41
AbsDiffInElements(const size_t first_size,const size_t second_size)42 size_t AbsDiffInElements(const size_t first_size, const size_t second_size) {
43 return first_size >= second_size ? first_size - second_size
44 : second_size - first_size;
45 }
46
AbsDiffInElements(const uint2 & first_size,const uint2 & second_size)47 size_t AbsDiffInElements(const uint2& first_size, const uint2& second_size) {
48 const size_t first_elements_cnt = first_size.y * first_size.x;
49 const size_t second_elements_cnt = second_size.y * second_size.x;
50 return first_elements_cnt >= second_elements_cnt
51 ? first_elements_cnt - second_elements_cnt
52 : second_elements_cnt - first_elements_cnt;
53 }
54
AbsDiffInElements(const uint3 & first_size,const uint3 & second_size)55 size_t AbsDiffInElements(const uint3& first_size, const uint3& second_size) {
56 const size_t first_elements_cnt = first_size.z * first_size.y * first_size.x;
57 const size_t second_elements_cnt =
58 second_size.z * second_size.y * second_size.x;
59 return first_elements_cnt >= second_elements_cnt
60 ? first_elements_cnt - second_elements_cnt
61 : second_elements_cnt - first_elements_cnt;
62 }
63
CalculateTaskProfiles(const std::vector<TensorUsageRecord<size_t>> & usage_records)64 std::vector<TaskProfile> CalculateTaskProfiles(
65 const std::vector<TensorUsageRecord<size_t>>& usage_records) {
66 TaskId num_tasks = 0;
67 for (size_t i = 0; i < usage_records.size(); ++i) {
68 num_tasks = std::max(num_tasks, usage_records[i].last_task + 1);
69 }
70 std::vector<TaskProfile> task_profiles(num_tasks);
71 for (size_t rec_id = 0; rec_id < usage_records.size(); ++rec_id) {
72 // Each tensor usage record must be added to profile of every task between
73 // its first_task and last_task.
74 for (TaskId task_id = usage_records[rec_id].first_task;
75 task_id <= usage_records[rec_id].last_task; ++task_id) {
76 task_profiles[task_id].emplace_back(&usage_records[rec_id], rec_id);
77 }
78 }
79 // Records in each TaskProfile must be sorted in non-increasing order of
80 // corresponding tensors sizes.
81 for (auto& task_profile : task_profiles) {
82 std::sort(task_profile.begin(), task_profile.end(), CompareBySize);
83 }
84 return task_profiles;
85 }
86
CalculatePositionalMaximums(const std::vector<TensorUsageRecord<size_t>> & usage_records)87 std::vector<size_t> CalculatePositionalMaximums(
88 const std::vector<TensorUsageRecord<size_t>>& usage_records) {
89 std::vector<TaskProfile> task_profiles = CalculateTaskProfiles(usage_records);
90 std::vector<size_t> positional_max;
91 for (const auto& task_profile : task_profiles) {
92 // Update positional_max with values of current TaskProfile.
93 size_t i = 0;
94 for (; i < task_profile.size() && i < positional_max.size(); ++i) {
95 positional_max[i] = std::max(positional_max[i],
96 task_profile[i].usage_record->tensor_size);
97 }
98 // If current task_profile has more records, than there are in
99 // positional_max, we should append new elements into positional_max.
100 for (; i < task_profile.size(); ++i) {
101 positional_max.push_back(task_profile[i].usage_record->tensor_size);
102 }
103 }
104 return positional_max;
105 }
106
107 } // namespace gpu
108 } // namespace tflite
109