[Valgrind] Remove valgrind warnings.
[platform/adaptation/npu/trix-engine.git] / src / core / ne-profiler.cc
1 /**
2  * Proprietary
3  * Copyright (C) 2021 Samsung Electronics
4  * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
5  */
6 /**
7  * @file ne-profiler.cc
8  * @date 25 Mar 2021
9  * @brief Model profiler for NPU Engine (NE) users.
10  * @author Dongju Chae <dongju.chae@samsung.com>
11  * @bug No known bugs except for NYI items
12  */
13
14 #include "ne-profiler.h"
15
16 ModelProfiler::ModelProfiler (const DriverAPI *api) : api_ (api) {}
17
18 ModelProfiler::~ModelProfiler () {
19   profile_map_.clear ();
20 }
21
22 int
23 ModelProfiler::appendRequest (int req_id, const Model *model) {
24   ProfileData *data = new ProfileData (req_id, model);
25   return profile_map_.insert (req_id, data);
26 }
27
28 int
29 ModelProfiler::removeRequest (int req_id) {
30   return profile_map_.remove (req_id);
31 }
32
33 int
34 ModelProfiler::getProfile (int req_id, const npu_profile_opt &opt, npu_profile *profile) {
35   ProfileData *data = profile_map_.find (req_id);
36   if (data == nullptr)
37     return -ENOENT;
38
39   const Model *model = data->getModel ();
40   if (model == nullptr)
41     return -EINVAL;
42
43   int status = api_->getProfile (req_id, profile);
44   if (status != 0)
45     return status;
46
47   if (opt.level == PROFILE_LEVEL_EXT_META || opt.level == PROFILE_LEVEL_LAYER) {
48     HWmem *extended = model->getExtendedMetadata ();
49     if (extended != nullptr)
50       manipulateProfile (extended, profile);
51     else if (opt.level == PROFILE_LEVEL_LAYER)
52       status = -EINVAL;
53   }
54
55   profile_map_.remove (req_id);
56   return status;
57 }
58
59 void
60 ModelProfiler::manipulateProfile (HWmem *extended, npu_profile *profile) {
61   npubin_meta_profile *meta_profile =
62       reinterpret_cast<npubin_meta_profile *> (extended->getData ());
63   npu_profile_layer *new_layers = new npu_profile_layer[meta_profile->node_entry_num + 1];
64
65   npu_profile_layer *unclassified = &new_layers[meta_profile->node_entry_num];
66
67   snprintf (unclassified->name, NPU_OPNAME_MAX - 1, "%s", "Unclassified");
68   unclassified->name[NPU_OPNAME_MAX - 1] = '\x00';
69   unclassified->node_id = -1;
70
71   unclassified->running_cycles = 0;
72   unclassified->start_cycles = 0;
73   unclassified->end_cycles = 0;
74   unclassified->dram_read_bytes = 0;
75   unclassified->dram_write_bytes = 0;
76   unclassified->sram_read_bytes = 0;
77   unclassified->sram_write_bytes = 0;
78
79   /** 1) parsing node table */
80   std::unordered_map<uint32_t, npu_profile_layer *> node_table;
81   uint32_t pos = 0;
82
83   node_table.reserve (meta_profile->node_entry_num);
84
85   for (uint32_t i = 0; i < meta_profile->node_entry_num; i++) {
86     uint32_t id, length;
87
88     memcpy (&id, meta_profile->entry_data + pos, sizeof (uint32_t));
89     pos += sizeof (uint32_t);
90
91     memcpy (&length, meta_profile->entry_data + pos, sizeof (uint32_t));
92     pos += sizeof (uint32_t);
93
94     if (length == 0) {
95       std::cerr << "Zero length detected at ";
96       std::cerr << id << "th node" << std::endl;
97
98       delete[] new_layers;
99       return;
100     }
101
102     std::string name (meta_profile->entry_data + pos);
103     pos += length;
104
105     npu_profile_layer *layer = &new_layers[i];
106
107     snprintf (layer->name, NPU_OPNAME_MAX - 1, "%s", name.c_str ());
108     layer->name[NPU_OPNAME_MAX - 1] = '\x00';
109     layer->node_id = id;
110
111     layer->running_cycles = 0;
112     layer->start_cycles = 0;
113     layer->end_cycles = 0;
114     layer->dram_read_bytes = 0;
115     layer->dram_write_bytes = 0;
116     layer->sram_read_bytes = 0;
117     layer->sram_write_bytes = 0;
118
119     node_table.insert (std::make_pair (id, layer));
120   }
121
122   /** 2) parsing visa table */
123   pos = meta_profile->node_table_size;
124   for (uint32_t i = 0; i < meta_profile->visa_entry_num; i++) {
125     uint32_t id, node_num;
126
127     memcpy (&id, meta_profile->entry_data + pos, sizeof (uint32_t));
128     pos += sizeof (uint32_t);
129
130     memcpy (&node_num, meta_profile->entry_data + pos, sizeof (uint32_t));
131     pos += sizeof (uint32_t);
132
133     if (node_num > 0) {
134       uint32_t *node_ids = (uint32_t *) (meta_profile->entry_data + pos);
135
136       for (uint32_t j = 0; j < node_num; j++) {
137         uint32_t node_id = node_ids[j];
138         auto it = node_table.find (node_id);
139
140         if (it != node_table.end ()) {
141           npu_profile_layer *layer = it->second;
142
143           /** TODO: evenly divided to fused layers */
144           layer->running_cycles += profile->layers[i].running_cycles / node_num;
145           if (layer->start_cycles == 0)
146             layer->start_cycles = profile->layers[i].start_cycles;
147           if (layer->end_cycles < profile->layers[i].end_cycles)
148             layer->end_cycles = profile->layers[i].end_cycles;
149           layer->dram_read_bytes += profile->layers[i].dram_read_bytes / node_num;
150           layer->dram_write_bytes += profile->layers[i].dram_write_bytes / node_num;
151           layer->sram_read_bytes += profile->layers[i].sram_read_bytes / node_num;
152           layer->sram_write_bytes += profile->layers[i].sram_write_bytes / node_num;
153           layer->visa_exec_seq = -1;
154         } else {
155           std::cerr << "Unable to find the node ID " << node_id << std::endl;
156         }
157       }
158     } else {
159       unclassified->running_cycles += profile->layers[i].running_cycles;
160       unclassified->dram_read_bytes += profile->layers[i].dram_read_bytes;
161       unclassified->dram_write_bytes += profile->layers[i].dram_write_bytes;
162       unclassified->sram_read_bytes += profile->layers[i].sram_read_bytes;
163       unclassified->sram_write_bytes += profile->layers[i].sram_write_bytes;
164       unclassified->visa_exec_seq = -1;
165     }
166
167     pos += sizeof (uint32_t) * node_num;
168   }
169
170   /** 3) profile data mapping */
171   size_t num_layers = node_table.size ();
172   if (num_layers > 0) {
173     delete[] profile->layers;
174
175     profile->layers = new_layers;
176     profile->num_layers = num_layers + 1;
177   } else {
178     delete[] new_layers;
179   }
180 }