paddle/fluid/platform/profiler.cc
void ParseEvents(const std::vector<std::vector<Event>>& events,
                 EventSortingKey sorted_by = EventSortingKey::kDefault) {
  if (g_state == ProfilerState::kDisabled) return;

  std::string sorted_domain;
  std::function<bool(const EventItem&, const EventItem&)> sorted_func;
  switch (sorted_by) {
    case EventSortingKey::kCalls:
      sorted_domain = "number of calls";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.calls > b.calls;
      };
      break;
    case EventSortingKey::kTotal:
      sorted_domain = "total time";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.total_time > b.total_time;
      };
      break;
    case EventSortingKey::kMin:
      sorted_domain = "minimum time";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.min_time > b.min_time;
      };
      break;
    case EventSortingKey::kMax:
      sorted_domain = "maximum time";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.max_time > b.max_time;
      };
      break;
    case EventSortingKey::kAve:
      sorted_domain = "average time";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.ave_time > b.ave_time;
      };
      break;
    default:
      sorted_domain = "event first end time";
  }

  std::vector<std::vector<EventItem>> events_table;
  size_t max_name_width = 0;
  for (size_t i = 0; i < events.size(); i++) {
    std::list<Event> pushed_events;
    std::vector<EventItem> event_items;
    std::unordered_map<std::string, int> event_idx;

    for (size_t j = 0; j < events[i].size(); j++) {
      if (events[i][j].type() == EventType::kPushRange) {
        pushed_events.push_back(events[i][j]);
      } else if (events[i][j].type() == EventType::kPopRange) {
        std::list<Event>::reverse_iterator rit = pushed_events.rbegin();
        while (rit != pushed_events.rend() &&
               rit->name() != events[i][j].name()) {
          ++rit;
        }

        if (rit != pushed_events.rend()) {
          double event_time = (g_state == ProfilerState::kCUDA ||
                               g_state == ProfilerState::kAll)
                                  ? rit->CudaElapsedMs(events[i][j])
                                  : rit->CpuElapsedMs(events[i][j]);

          std::string event_name =
              "thread" + std::to_string(rit->thread_id()) + "::" + rit->name();
          max_name_width = std::max(max_name_width, event_name.size());

          if (event_idx.find(event_name) == event_idx.end()) {
            event_idx[event_name] = event_items.size();
            EventItem event_item = {event_name, 1,          event_time,
                                    event_time, event_time, event_time};
            event_items.push_back(event_item);
          } else {
            int index = event_idx[event_name];
            event_items[index].calls += 1;
            // total time
            event_items[index].total_time += event_time;
            // min time
            event_items[index].min_time =
                std::min(event_time, event_items[index].min_time);
            // max time
            event_items[index].max_time =
                std::max(event_time, event_items[index].max_time);
          }

          // remove the push marker from the list
          pushed_events.erase((++rit).base());
        } else {
          LOG(WARNING) << "Cannot find the push marker of event \'"
                       << events[i][j].name()
                       << "\', which will be ignored in profiling report.";
        }
      }
    }
    // average time
    for (auto& item : event_items) {
      item.ave_time = item.total_time / item.calls;
    }
    // sort
    if (sorted_by != EventSortingKey::kDefault) {
      std::sort(event_items.begin(), event_items.end(), sorted_func);
    }

    events_table.push_back(event_items);
    // log warning if there are events with `push` but without `pop`
    std::list<Event>::reverse_iterator rit = pushed_events.rbegin();
    while (rit != pushed_events.rend()) {
      LOG(WARNING) << "Cannot find the pop marker of event \'" << rit->name()
                   << "\', which will be ignored in profiling report.";
      ++rit;
    }
  }

  // Print report
  PrintProfiler(events_table, sorted_domain, max_name_width + 4, 12);
}
// Parse the event list and output the profiling report
Parse the event list and output the profiling report
Parse the event list and output the profiling report
void ParseEvents(const std::vector<std::vector<Event>>& events,
                 EventSortingKey sorted_by = EventSortingKey::kDefault) {
  if (g_state == ProfilerState::kDisabled) return;
  std::string sorted_domain;
  std::function<bool(const EventItem&, const EventItem&)> sorted_func;
  switch (sorted_by) {
    case EventSortingKey::kCalls:
      sorted_domain = "number of calls";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.calls > b.calls;
      };
      break;
    case EventSortingKey::kTotal:
      sorted_domain = "total time";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.total_time > b.total_time;
      };
      break;
    case EventSortingKey::kMin:
      sorted_domain = "minimum time";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.min_time > b.min_time;
      };
      break;
    case EventSortingKey::kMax:
      sorted_domain = "maximum time";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.max_time > b.max_time;
      };
      break;
    case EventSortingKey::kAve:
      sorted_domain = "average time";
      sorted_func = [](const EventItem& a, const EventItem& b) {
        return a.ave_time > b.ave_time;
      };
      break;
    default:
      sorted_domain = "event first end time";
  }
  std::vector<std::vector<EventItem>> events_table;
  size_t max_name_width = 0;
  for (size_t i = 0; i < events.size(); i++) {
    std::list<Event> pushed_events;
    std::vector<EventItem> event_items;
    std::unordered_map<std::string, int> event_idx;
    for (size_t j = 0; j < events[i].size(); j++) {
      if (events[i][j].type() == EventType::kPushRange) {
        pushed_events.push_back(events[i][j]);
      } else if (events[i][j].type() == EventType::kPopRange) {
        std::list<Event>::reverse_iterator rit = pushed_events.rbegin();
        while (rit != pushed_events.rend() &&
               rit->name() != events[i][j].name()) {
          ++rit;
        }
        if (rit != pushed_events.rend()) {
          double event_time = (g_state == ProfilerState::kCUDA ||
                               g_state == ProfilerState::kAll)
                                  ? rit->CudaElapsedMs(events[i][j])
                                  : rit->CpuElapsedMs(events[i][j]);
          std::string event_name =
              "thread" + std::to_string(rit->thread_id()) + "::" + rit->name();
          max_name_width = std::max(max_name_width, event_name.size());
          if (event_idx.find(event_name) == event_idx.end()) {
            event_idx[event_name] = event_items.size();
            EventItem event_item = {event_name, 1,          event_time,
                                    event_time, event_time, event_time};
            event_items.push_back(event_item);
          } else {
            int index = event_idx[event_name];
            event_items[index].calls += 1;
            event_items[index].total_time += event_time;
            event_items[index].min_time =
                std::min(event_time, event_items[index].min_time);
            event_items[index].max_time =
                std::max(event_time, event_items[index].max_time);
          }
          pushed_events.erase((++rit).base());
        } else {
          LOG(WARNING) << "Cannot find the push marker of event \'"
                       << events[i][j].name()
                       << "\', which will be ignored in profiling report.";
        }
      }
    }
    for (auto& item : event_items) {
      item.ave_time = item.total_time / item.calls;
    }
    if (sorted_by != EventSortingKey::kDefault) {
      std::sort(event_items.begin(), event_items.end(), sorted_func);
    }
    events_table.push_back(event_items);
    std::list<Event>::reverse_iterator rit = pushed_events.rbegin();
    while (rit != pushed_events.rend()) {
      LOG(WARNING) << "Cannot find the pop marker of event \'" << rit->name()
                   << "\', which will be ignored in profiling report.";
      ++rit;
    }
  }
  PrintProfiler(events_table, sorted_domain, max_name_width + 4, 12);
}
void ParseEvents ( const std :: vector < std :: vector < Event > > & events , EventSortingKey sorted_by = EventSortingKey :: kDefault ) { if ( g_state == ProfilerState :: kDisabled ) return ; std :: string sorted_domain ; std :: function < bool ( const EventItem & , const EventItem & ) > sorted_func ; switch ( sorted_by ) { case EventSortingKey :: kCalls : sorted_domain = " " ; sorted_func = [ ] ( const EventItem & a , const EventItem & b ) { return a . calls > b . calls ; } ; break ; case EventSortingKey :: kTotal : sorted_domain = " " ; sorted_func = [ ] ( const EventItem & a , const EventItem & b ) { return a . total_time > b . total_time ; } ; break ; case EventSortingKey :: kMin : sorted_domain = " " ; sorted_func = [ ] ( const EventItem & a , const EventItem & b ) { return a . min_time > b . min_time ; } ; break ; case EventSortingKey :: kMax : sorted_domain = " " ; sorted_func = [ ] ( const EventItem & a , const EventItem & b ) { return a . max_time > b . max_time ; } ; break ; case EventSortingKey :: kAve : sorted_domain = " " ; sorted_func = [ ] ( const EventItem & a , const EventItem & b ) { return a . ave_time > b . ave_time ; } ; break ; default : sorted_domain = " " ; } std :: vector < std :: vector < EventItem > > events_table ; size_t max_name_width = 0 ; for ( size_t i = 0 ; i < events . size ( ) ; i ++ ) { std :: list < Event > pushed_events ; std :: vector < EventItem > event_items ; std :: unordered_map < std :: string , int > event_idx ; for ( size_t j = 0 ; j < events [ i ] . size ( ) ; j ++ ) { if ( events [ i ] [ j ] . type ( ) == EventType :: kPushRange ) { pushed_events . push_back ( events [ i ] [ j ] ) ; } else if ( events [ i ] [ j ] . type ( ) == EventType :: kPopRange ) { std :: list < Event > :: reverse_iterator rit = pushed_events . rbegin ( ) ; while ( rit != pushed_events . rend ( ) && rit -> name ( ) != events [ i ] [ j ] . name ( ) ) { ++ rit ; } if ( rit != pushed_events . rend ( ) ) { double event_time = ( g_state == ProfilerState :: kCUDA || g_state == ProfilerState :: kAll ) ? rit -> CudaElapsedMs ( events [ i ] [ j ] ) : rit -> CpuElapsedMs ( events [ i ] [ j ] ) ; std :: string event_name = " " + std :: to_string ( rit -> thread_id ( ) ) + " " + rit -> name ( ) ; max_name_width = std :: max ( max_name_width , event_name . size ( ) ) ; if ( event_idx . find ( event_name ) == event_idx . end ( ) ) { event_idx [ event_name ] = event_items . size ( ) ; EventItem event_item = { event_name , 1 , event_time , event_time , event_time , event_time } ; event_items . push_back ( event_item ) ; } else { int index = event_idx [ event_name ] ; event_items [ index ] . calls += 1 ; event_items [ index ] . total_time += event_time ; event_items [ index ] . min_time = std :: min ( event_time , event_items [ index ] . min_time ) ; event_items [ index ] . max_time = std :: max ( event_time , event_items [ index ] . max_time ) ; } pushed_events . erase ( ( ++ rit ) . base ( ) ) ; } else { LOG ( WARNING ) << " \' " << events [ i ] [ j ] . name ( ) << " \' " ; } } } for ( auto & item : event_items ) { item . ave_time = item . total_time / item . calls ; } if ( sorted_by != EventSortingKey :: kDefault ) { std :: sort ( event_items . begin ( ) , event_items . end ( ) , sorted_func ) ; } events_table . push_back ( event_items ) ; std :: list < Event > :: reverse_iterator rit = pushed_events . rbegin ( ) ; while ( rit != pushed_events . rend ( ) ) { LOG ( WARNING ) << " \' " << rit -> name ( ) << " \' " ; ++ rit ; } } PrintProfiler ( events_table , sorted_domain , max_name_width + 4 , 12 ) ; }
Parse the event list and output the profiling report
Parse the event list and output the profiling report
// total time // min time // max time // remove the push marker from the list // average time // sort // log warning if there are events with `push` but without `pop` // Print report