11#pragma once
22#include < algorithm>
33#include < chrono>
4+ #include < iomanip>
45#include < memory>
56#include < queue>
67#include < stdexcept>
1415#include " runtime_options.hpp"
1516
1617namespace it_lab_ai {
18+ static std::unordered_map<LayerType, std::string> label_map = {
19+ {kInput , " Input" },
20+ {kPooling , " Pooling" },
21+ {kElementWise , " Element-wise" },
22+ {kConvolution , " Convolution" },
23+ {kFullyConnected , " Dense" },
24+ {kFlatten , " Flatten" },
25+ {kConcat , " Concat" },
26+ {kDropout , " Dropout" },
27+ {kSplit , " Split" },
28+ {kBinaryOp , " BinaryOp" },
29+ {kTranspose , " Transpose" },
30+ {kMatmul , " MatMul" },
31+ {kReshape , " Reshape" },
32+ {kSoftmax , " Softmax" },
33+ {kReduce , " Reduce" },
34+ {kBatchNormalization , " Normalization" }};
35+
36+ struct LayerTimeStats {
37+ std::string layer_name;
38+ double total_time = 0.0 ;
39+ int call_count = 0 ;
40+ double min_time = std::numeric_limits<double >::max();
41+ double max_time = 0.0 ;
42+ };
1743
1844struct BranchState {
1945 int ind_layer;
@@ -27,6 +53,7 @@ std::shared_ptr<Layer> layer_based_shared_copy(
2753 const std::shared_ptr<Layer>& layer, const RuntimeOptions& options);
2854
2955class Graph {
56+ std::map<std::string, LayerTimeStats> layer_stats_;
3057 int BiggestSize_;
3158 int V_ ; // amount of ids
3259 std::vector<std::shared_ptr<Layer>> layers_;
@@ -83,34 +110,38 @@ class Graph {
83110 split_distribution_ = std::move (split_dist);
84111 }
85112
86- [[nodiscard]] int getVertexValue (size_t layerID) const {
87- if (layerID >= arrayV_.size ()) {
88- throw std::invalid_argument (" ArrayV does not contain this ID." );
89- }
90- return arrayV_[layerID];
91- }
92-
93- [[nodiscard]] int getEdgeValue (size_t pos) const {
94- if (pos >= arrayE_.size ()) {
95- throw std::invalid_argument (" ArrayE does not contain this." );
96- }
97- return arrayE_[pos];
98- }
99-
100113 [[nodiscard]] size_t getInputsSize (size_t layerID) const {
101114 if (layerID >= in_edges_.size ()) {
102- throw std::invalid_argument (" Input edges array do not contain this ID." );
115+ throw std::invalid_argument (
116+ " Input edges array does not contain this ID." );
103117 }
104118 return in_edges_[layerID].size ();
105119 }
106120
107121 [[nodiscard]] std::vector<int > getInLayers (size_t layerID) const {
108122 if (layerID >= in_edges_.size ()) {
109- throw std::invalid_argument (" Input edges array do not contain this ID." );
123+ throw std::invalid_argument (
124+ " Input edges array does not contain this ID." );
110125 }
111126 return in_edges_[layerID];
112127 }
113128
129+ [[nodiscard]] size_t getOutputsSize (size_t layerID) const {
130+ if (layerID >= layers_.size ()) {
131+ throw std::invalid_argument (" Layers array does not contain this ID." );
132+ }
133+ return arrayV_[layerID + 1 ] - arrayV_[layerID];
134+ }
135+
136+ [[nodiscard]] std::vector<int > getOutLayers (size_t layerID) const {
137+ if (layerID >= layers_.size ()) {
138+ throw std::invalid_argument (
139+ " Output edges array does not contain this ID." );
140+ }
141+ return std::vector<int >(arrayE_.begin () + arrayV_[layerID],
142+ arrayE_.begin () + arrayV_[layerID + 1 ]);
143+ }
144+
114145 [[nodiscard]] int getLayersCount () const { return V_ ; }
115146
116147 [[nodiscard]] std::shared_ptr<Layer> getLayerFromID (size_t layerID) const {
@@ -237,8 +268,9 @@ class Graph {
237268 }
238269 // remove outputs
239270 int amount_connected = arrayV_[id + 1 ] - arrayV_[id];
271+ std::vector<int > array_e_copy = arrayE_;
240272 for (int i = 0 ; i < amount_connected; i++) {
241- removeConnection (id, arrayE_ [arrayV_[id] + i]);
273+ removeConnection (id, array_e_copy [arrayV_[id] + i]);
242274 }
243275 // remove vertex
244276 in_edges_.erase (in_edges_.begin () + id);
@@ -378,8 +410,27 @@ class Graph {
378410 auto end = std::chrono::high_resolution_clock::now ();
379411 auto elapsed =
380412 std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
381- time_.push_back (static_cast <int >(elapsed.count ()));
382- time_layer_.push_back (layers_[current_layer]->getName ());
413+ int elapsed_ms = static_cast <int >(elapsed.count ());
414+ time_.push_back (elapsed_ms);
415+
416+ LayerType layer_type = layers_[current_layer]->getName ();
417+ time_layer_.push_back (layer_type);
418+
419+ auto it = label_map.find (layer_type);
420+ std::string layer_name_str =
421+ (it != label_map.end ()) ? it->second : " Unknown" ;
422+
423+ auto & stats = layer_stats_[layer_name_str];
424+ stats.total_time += elapsed_ms;
425+ stats.call_count ++;
426+
427+ if (stats.call_count == 1 ) {
428+ stats.min_time = elapsed_ms;
429+ stats.max_time = elapsed_ms;
430+ } else {
431+ if (elapsed_ms < stats.min_time ) stats.min_time = elapsed_ms;
432+ if (elapsed_ms > stats.max_time ) stats.max_time = elapsed_ms;
433+ }
383434#endif
384435 }
385436 }
@@ -403,25 +454,6 @@ class Graph {
403454#ifdef ENABLE_STATISTIC_TIME
404455 std::vector<std::string> getTimeInfo () {
405456 std::vector<std::string> res;
406-
407- std::unordered_map<LayerType, std::string> label_map = {
408- {kInput , " Input" },
409- {kPooling , " Pooling" },
410- {kElementWise , " Element-wise" },
411- {kConvolution , " Convolution" },
412- {kFullyConnected , " Dense" },
413- {kFlatten , " Flatten" },
414- {kConcat , " Concat" },
415- {kDropout , " Dropout" },
416- {kSplit , " Split" },
417- {kBinaryOp , " BinaryOp" },
418- {kTranspose , " Transpose" },
419- {kMatmul , " MatMul" },
420- {kReshape , " Reshape" },
421- {kSoftmax , " Softmax" },
422- {kReduce , " Reduce" },
423- {kBatchNormalization , " Normalization" }};
424-
425457 for (size_t i = 0 ; i < time_.size (); i++) {
426458 auto it = label_map.find (time_layer_[i]);
427459 std::string layer_name = (it != label_map.end ()) ? it->second : " Unknown" ;
@@ -456,6 +488,23 @@ class Graph {
456488 return result;
457489 }
458490
491+ void printLayerStats () {
492+ std::cout << " \n ========== LAYER PERFORMANCE STATISTICS ==========\n " ;
493+ std::cout << std::left << std::setw (20 ) << " Layer Type" << std::right
494+ << std::setw (15 ) << " Total (ms)" << std::setw (12 ) << " Calls"
495+ << std::setw (15 ) << " Avg (ms)" << std::setw (15 ) << " Min (ms)"
496+ << std::setw (15 ) << " Max (ms)" << ' \n ' ;
497+
498+ for (const auto & [name, stats] : layer_stats_) {
499+ double avg = stats.total_time / stats.call_count ;
500+ std::cout << std::left << std::setw (20 ) << name << std::right
501+ << std::fixed << std::setprecision (3 ) << std::setw (15 )
502+ << stats.total_time << std::setw (12 ) << stats.call_count
503+ << std::setw (15 ) << avg << std::setw (15 ) << stats.min_time
504+ << std::setw (15 ) << stats.max_time << ' \n ' ;
505+ }
506+ }
507+
459508 [[nodiscard]] std::vector<int > getTraversalOrder () const {
460509 auto in_out_degrees = getInOutDegrees ();
461510 std::vector<int > in_degree (V_ );
0 commit comments