[Profile] Support layer manipulation in kernel profiling
[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)
17   : api_ (api)
18 {
19 }
20
21 ModelProfiler::~ModelProfiler ()
22 {
23   profile_map_.clear ();
24 }
25
26 int
27 ModelProfiler::appendTask (int task_id, const Model * model)
28 {
29   ProfileData * data = new ProfileData (task_id, model);
30   return profile_map_.insert (task_id, data);
31 }
32
33 int
34 ModelProfiler::getTaskProfile (int task_id, npu_profile *profile)
35 {
36   ProfileData * data = profile_map_.find (task_id);
37   if (data == nullptr)
38     return -ENOENT;
39
40   const Model * model = data->getModel ();
41   if (model == nullptr)
42     return -EINVAL;
43
44   int status = api_->getProfile (task_id, profile);
45   if (status != 0)
46     return status;
47
48   HWmem * extended = model->getExtendedMetadata ();
49   if (extended != nullptr)
50     manipulateProfile (extended, profile);
51
52   profile_map_.remove (task_id);
53
54   return 0;
55 }
56
57 void
58 ModelProfiler::manipulateProfile (HWmem * extended, npu_profile *profile)
59 {
60   npubin_meta_profile *meta_profile =
61     reinterpret_cast <npubin_meta_profile *> (extended->getData ());
62   npu_profile_layer * new_layers =
63     new npu_profile_layer[meta_profile->node_entry_num + 1];
64
65   npu_profile_layer * unclassified =
66     &new_layers[meta_profile->node_entry_num];
67
68   snprintf (unclassified->name, NPU_OPNAME_MAX - 1, "%s", "Unclassified");
69   unclassified->name[NPU_OPNAME_MAX - 1] = '\x00';
70   unclassified->node_id = -1;
71
72   unclassified->running_cycles = 0;
73   unclassified->dram_read_bytes = 0;
74   unclassified->dram_write_bytes = 0;
75   unclassified->sram_read_bytes = 0;
76   unclassified->sram_write_bytes = 0;
77
78   /** 1) parsing node table */
79   std::unordered_map<uint32_t, npu_profile_layer *> node_table;
80   uint32_t pos = 0;
81
82   node_table.reserve (meta_profile->node_entry_num);
83
84   for (uint32_t i = 0; i < meta_profile->node_entry_num; i++) {
85     uint32_t id, length;
86
87     memcpy (&id, meta_profile->entry_data + pos, sizeof (uint32_t));
88     pos += sizeof (uint32_t);
89
90     memcpy (&length, meta_profile->entry_data + pos, sizeof (uint32_t));
91     pos += sizeof (uint32_t);
92
93     if (length == 0) {
94       std::cerr << "Zero length detected at ";
95       std::cerr << id << "th node" << std::endl;
96
97       delete [] new_layers;
98       return;
99     }
100
101     std::string name (meta_profile->entry_data + pos);
102     pos += length;
103
104     npu_profile_layer * layer = &new_layers[i];
105
106     snprintf (layer->name, NPU_OPNAME_MAX - 1, "%s", name.c_str ());
107     layer->name[NPU_OPNAME_MAX - 1] = '\x00';
108     layer->node_id = id;
109
110     layer->running_cycles = 0;
111     layer->dram_read_bytes = 0;
112     layer->dram_write_bytes = 0;
113     layer->sram_read_bytes = 0;
114     layer->sram_write_bytes = 0;
115
116     node_table.insert(std::make_pair(id, layer));
117   }
118
119   /** 2) parsing visa table */
120   pos = meta_profile->node_table_size;
121   for (uint32_t i = 0; i < meta_profile->visa_entry_num; i++) {
122     uint32_t id, node_num;
123
124     memcpy (&id, meta_profile->entry_data + pos, sizeof (uint32_t));
125     pos += sizeof (uint32_t);
126
127     memcpy (&node_num, meta_profile->entry_data + pos, sizeof (uint32_t));
128     pos += sizeof (uint32_t);
129
130     if (node_num > 0) {
131       uint32_t * node_ids = (uint32_t *) (meta_profile->entry_data + pos);
132
133       for (uint32_t j = 0; j < node_num; j++) {
134         uint32_t node_id = node_ids[j];
135         auto it = node_table.find (node_id);
136
137         if (it != node_table.end ()) {
138           npu_profile_layer * layer = it->second;
139
140           /** TODO: evenly divided to fused layers */
141           layer->running_cycles += profile->layers[i].running_cycles / node_num;
142           layer->dram_read_bytes += profile->layers[i].dram_read_bytes / node_num;
143           layer->dram_write_bytes += profile->layers[i].dram_write_bytes / node_num;
144           layer->sram_read_bytes += profile->layers[i].sram_read_bytes / node_num;
145           layer->sram_write_bytes += profile->layers[i].sram_write_bytes / node_num;
146           layer->visa_exec_seq = -1;
147         } else {
148           std::cerr << "Unable to find the node ID " << node_id << std::endl;
149         }
150       }
151     } else {
152       unclassified->running_cycles += profile->layers[i].running_cycles;
153       unclassified->dram_read_bytes += profile->layers[i].dram_read_bytes;
154       unclassified->dram_write_bytes += profile->layers[i].dram_write_bytes;
155       unclassified->sram_read_bytes += profile->layers[i].sram_read_bytes;
156       unclassified->sram_write_bytes += profile->layers[i].sram_write_bytes;
157       unclassified->visa_exec_seq = -1;
158     }
159
160     pos += sizeof (uint32_t) * node_num;
161   }
162
163   /** 3) profile data mapping */
164   size_t num_layers = node_table.size ();
165   if (num_layers > 0) {
166     delete [] profile->layers;
167
168     profile->layers = new_layers;
169     profile->num_layers = num_layers + 1;
170   } else {
171     delete [] new_layers;
172   }
173 }
174
175