Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_PAPI_Counter2.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 #include "Panzer_PAPI_Counter2.hpp"
44 #include "Teuchos_Assert.hpp"
45 #include "Teuchos_CommHelpers.hpp"
46 #include <algorithm>
47 #include <cstring>
48 
49 namespace panzer {
50 
51  int PAPICounter2::m_event_set = PAPI_NULL;
52  std::vector<int> PAPICounter2::m_events;
53  bool PAPICounter2::m_is_initialized = false;
54  std::map<std::string,PAPICounter2::InternalCounter2> PAPICounter2::m_counters;
55 
58  PAPICounter2::PAPICounter2(const std::string counter_name) :
59  m_name(counter_name)
60  {
61  if (!m_is_initialized) {
62  TEUCHOS_ASSERT( PAPI_library_init(PAPI_VER_CURRENT) == PAPI_VER_CURRENT );
63 
64  TEUCHOS_ASSERT( PAPI_create_eventset(&m_event_set) == PAPI_OK );
65 
66  for (std::vector<int>::const_iterator event = m_events.begin();
67  event != m_events.end(); ++event) {
68  TEUCHOS_ASSERT( PAPI_add_event(m_event_set,*event) == PAPI_OK );
69  }
70 
71  TEUCHOS_ASSERT( PAPI_start(m_event_set) == PAPI_OK );
72  m_is_initialized = true;
73  }
74 
75  // initialize the specific timer first time in
76  std::map<std::string,InternalCounter2>::const_iterator counter;
77  counter = m_counters.find(m_name);
78  if (counter == m_counters.end()) {
80  c.accumulated_time = 0;
81  c.start_counters.resize(m_events.size());
82  c.stop_counters.resize(m_events.size());
83  c.accumulated_counters.resize(m_events.size());
84  c.num_calls = 0;
85  }
86 
87  // mark start time
89  TEUCHOS_ASSERT( PAPI_read(m_event_set, &(c.start_counters[0])) == PAPI_OK );
90  c.start_time = PAPI_get_real_usec();
91  c.num_calls +=1;
92  }
93 
95  {
96  // accumulate totals
98 
99  TEUCHOS_ASSERT( PAPI_read(m_event_set, &(c.stop_counters[0])) == PAPI_OK );
100  c.accumulated_time += PAPI_get_real_usec() - c.start_time;
101 
102  std::vector<long_long>::iterator accum = c.accumulated_counters.begin();
103  std::vector<long_long>::const_iterator start = c.start_counters.begin();
104  std::vector<long_long>::const_iterator stop = c.stop_counters.begin();
105  for (; accum != c.accumulated_counters.end(); ++accum,++start,++stop)
106  *accum += *stop - *start;
107 
108  }
109 
110  void PAPICounter2::addEventCounter(const int event)
111  {
113  std::logic_error,
114  "Error - cannot add event after PAPICounter is initialized!");
115 
116  m_events.push_back(event);
117  }
118 
120  {
121  TEUCHOS_ASSERT(PAPI_start(m_event_set) == PAPI_OK);
122  }
123 
125  {
126  //TEUCHOS_ASSERT(PAPI_stop(m_event_set) == PAPI_OK);
127  }
128 
129  void PAPICounter2::report(std::ostream& os, const Teuchos::Comm<int>& comm)
130  {
131 
132  os << std::endl;
133  os << "************************************************************" << std::endl;
134  os << "* PAPI Counter Report (over all processes) " << std::endl;
135  os << "************************************************************" << std::endl;
136 
137  for (std::map<std::string,InternalCounter2>::const_iterator timer = m_counters.begin();
138  timer != m_counters.end(); ++timer) {
139 
140  // Communicate totals across processes
141 
142  const std::vector<long long int>& accum = timer->second.accumulated_counters;
143  std::vector<long long int> global_min(accum.size(),0);
144  std::vector<long long int> global_max(accum.size(),0);
145  std::vector<long long int> global_sum(accum.size(),0);
146  std::vector<long long int> global_avg(accum.size(),0);
147  long long int average_time = 0;
148 
149  Teuchos::reduceAll(comm, Teuchos::REDUCE_MIN, static_cast<int>(accum.size()), &accum[0], &global_min[0]);
150  Teuchos::reduceAll(comm, Teuchos::REDUCE_MAX, static_cast<int>(accum.size()), &accum[0], &global_max[0]);
151  Teuchos::reduceAll(comm, Teuchos::REDUCE_SUM, static_cast<int>(accum.size()), &accum[0], &global_sum[0]);
152  Teuchos::reduceAll(comm, Teuchos::REDUCE_SUM, static_cast<int>(accum.size()), &accum[0], &global_avg[0]);
153 
154  for (std::vector<long long int>::iterator i = global_avg.begin();
155  i != global_avg.end(); ++i)
156  (*i) = *i / Teuchos::as<long long int>(comm.getSize());
157 
158  Teuchos::reduceAll(comm, Teuchos::REDUCE_SUM, 1, &(timer->second.accumulated_time), &average_time);
159  average_time /= Teuchos::as<long long int>(comm.getSize());
160 
161  os << timer->first<< ": Average Process Time (seconds) = "
162  << timer->second.accumulated_time / 1.0e6 << std::endl;
163  os << timer->first<< ": Number of Calls = " << timer->second.num_calls << std::endl;
164 
165  int i=0;
166  for (std::vector<long_long>::const_iterator event=timer->second.accumulated_counters.begin();
167  event != timer->second.accumulated_counters.end(); ++event,++i) {
168  char event_name[PAPI_MAX_STR_LEN];
169  TEUCHOS_ASSERT( PAPI_event_code_to_name(m_events[i],event_name) == PAPI_OK);
170  std::string string_event_name(event_name);
171  os << timer->first << ": " << string_event_name << " = "
172  << "min:" << global_min[i]
173  << ", max:" << global_max[i]
174  << ", total:" << global_sum[i]
175  << ", avg:" << global_avg[i]
176  << std::endl;
177  }
178 
179  }
180 
181  os << "************************************************************" << std::endl;
182  }
183 
184 }
PAPICounter2(const std::string)
virtual int getSize() const =0
static bool m_is_initialized
true if the static members have been intitialized
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
std::string m_name
name of this counter
static std::map< std::string, InternalCounter2 > m_counters
maps the counter name to the data object
static void addEventCounter(const int event)
static void report(std::ostream &os, const Teuchos::Comm< int > &comm)
static std::vector< int > m_events
papi event index
static int m_event_set
PAPI event set.
#define TEUCHOS_ASSERT(assertion_test)