Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Profile.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
20 #ifndef GALOIS_RUNTIME_PROFILE_H
21 #define GALOIS_RUNTIME_PROFILE_H
22 
23 #include <cstdlib>
24 
25 #ifdef GALOIS_ENABLE_VTUNE
26 #include "ittnotify.h"
27 #endif
28 
29 #ifdef GALOIS_ENABLE_PAPI
30 extern "C" {
31 #include <papi.h>
32 #include <papiStdEventDefs.h>
33 }
34 #endif
35 
36 #include "galois/config.h"
37 #include "galois/Galois.h"
38 #include "galois/gIO.h"
39 #include "galois/Timer.h"
40 
41 namespace galois::runtime {
42 
43 #ifdef GALOIS_ENABLE_VTUNE
44 
45 template <typename F>
46 void profileVtune(const F& func, const char* region) {
47 
48  region = region ? region : "(NULL)";
49 
52  "profileVtune can only be called from master thread (thread 0)");
53 
54  __itt_resume();
55 
56  timeThis(func, region);
57 
58  __itt_pause();
59 }
60 
61 #else
62 
63 template <typename F>
64 void profileVtune(const F& func, const char* region) {
65 
66  region = region ? region : "(NULL)";
67  galois::gWarn("Vtune not enabled or found");
68 
69  timeThis(func, region);
70 }
71 
72 #endif
73 
74 #ifdef GALOIS_ENABLE_PAPI
75 
76 namespace internal {
77 
78 unsigned long papiGetTID(void);
79 
80 template <typename __T = void>
81 void papiInit() {
82 
83  /* Initialize the PAPI library */
84  int retval = PAPI_library_init(PAPI_VER_CURRENT);
85 
86  if (retval != PAPI_VER_CURRENT && retval > 0) {
87  GALOIS_DIE("PAPI library version mismatch: ", retval,
88  " != ", PAPI_VER_CURRENT);
89  }
90 
91  if (retval < 0) {
92  GALOIS_DIE("initialization error!");
93  }
94 
95  if ((retval = PAPI_thread_init(&papiGetTID)) != PAPI_OK) {
96  GALOIS_DIE("PAPI thread init failed");
97  }
98 }
99 
100 template <typename V1, typename V2>
101 void decodePapiEvents(const V1& eventNames, V2& papiEvents) {
102  for (size_t i = 0; i < eventNames.size(); ++i) {
103  char buf[256];
104  std::strcpy(buf, eventNames[i].c_str());
105  if (PAPI_event_name_to_code(buf, &papiEvents[i]) != PAPI_OK) {
106  GALOIS_DIE("failed to recognize eventName = ", eventNames[i],
107  ", event code: ", papiEvents[i]);
108  }
109  }
110 }
111 
112 template <typename V1, typename V2, typename V3>
113 void papiStart(V1& eventSets, V2& papiResults, V3& papiEvents) {
114  galois::on_each([&](const unsigned tid, const unsigned numT) {
115  if (PAPI_register_thread() != PAPI_OK) {
116  GALOIS_DIE("failed to register thread with PAPI");
117  }
118 
119  int& eventSet = *eventSets.getLocal();
120 
121  eventSet = PAPI_NULL;
122  papiResults.getLocal()->resize(papiEvents.size());
123 
124  if (PAPI_create_eventset(&eventSet) != PAPI_OK) {
125  GALOIS_DIE("failed to init event set");
126  }
127  if (PAPI_add_events(eventSet, papiEvents.data(), papiEvents.size()) !=
128  PAPI_OK) {
129  GALOIS_DIE("failed to add events");
130  }
131 
132  if (PAPI_start(eventSet) != PAPI_OK) {
133  GALOIS_DIE("failed to start PAPI");
134  }
135  });
136 }
137 
138 template <typename V1, typename V2, typename V3>
139 void papiStop(V1& eventSets, V2& papiResults, V3& eventNames,
140  const char* region) {
141  galois::on_each([&](const unsigned tid, const unsigned numT) {
142  int& eventSet = *eventSets.getLocal();
143 
144  if (PAPI_stop(eventSet, papiResults.getLocal()->data()) != PAPI_OK) {
145  GALOIS_DIE("PAPI_stop failed");
146  }
147 
148  if (PAPI_cleanup_eventset(eventSet) != PAPI_OK) {
149  GALOIS_DIE("PAPI_cleanup_eventset failed");
150  }
151 
152  if (PAPI_destroy_eventset(&eventSet) != PAPI_OK) {
153  GALOIS_DIE("PAPI_destroy_eventset failed");
154  }
155 
156  assert(eventNames.size() == papiResults.getLocal()->size() &&
157  "Both vectors should be of equal length");
158  for (size_t i = 0; i < eventNames.size(); ++i) {
159  galois::runtime::reportStat_Tsum(region, eventNames[i],
160  (*papiResults.getLocal())[i]);
161  }
162 
163  if (PAPI_unregister_thread() != PAPI_OK) {
164  GALOIS_DIE("failed to un-register thread with PAPI");
165  }
166  });
167 }
168 
169 template <typename C>
170 void splitCSVstr(const std::string& inputStr, C& output,
171  const char delim = ',') {
172  std::stringstream ss(inputStr);
173 
174  for (std::string item; std::getline(ss, item, delim);) {
175  output.push_back(item);
176  }
177 }
178 
179 } // end namespace internal
180 
181 template <typename F>
182 void profilePapi(const F& func, const char* region) {
183 
184  const char* const PAPI_VAR_NAME = "GALOIS_PAPI_EVENTS";
185  region = region ? region : "(NULL)";
186 
187  std::string eventNamesCSV;
188 
189  if (!galois::substrate::EnvCheck(PAPI_VAR_NAME, eventNamesCSV) ||
190  eventNamesCSV.empty()) {
192  "No Events specified. Set environment variable GALOIS_PAPI_EVENTS");
193  galois::timeThis(func, region);
194  return;
195  }
196 
197  internal::papiInit();
198 
199  std::vector<std::string> eventNames;
200 
201  internal::splitCSVstr(eventNamesCSV, eventNames);
202 
203  std::vector<int> papiEvents(eventNames.size());
204 
205  internal::decodePapiEvents(eventNames, papiEvents);
206 
209 
210  internal::papiStart(eventSets, papiResults, papiEvents);
211 
212  galois::timeThis(func, region);
213 
214  internal::papiStop(eventSets, papiResults, eventNames, region);
215 }
216 
217 #else
218 
219 template <typename F>
220 void profilePapi(const F& func, const char* region) {
221 
222  region = region ? region : "(NULL)";
223  galois::gWarn("PAPI not enabled or found");
224 
225  timeThis(func, region);
226 }
227 
228 #endif
229 
230 } // namespace galois::runtime
231 
232 #endif
void profileVtune(const F &func, const char *region)
Definition: Profile.h:64
#define GALOIS_DIE(...)
Definition: gIO.h:96
void reportStat_Tsum(const S1 &region, const S2 &category, const T &value)
Definition: Statistics.h:562
#define GALOIS_ASSERT(cond,...)
Like assert but unconditionally executed.
Definition: gIO.h:102
bool EnvCheck(const char *varName)
Return true if the Enviroment variable is set.
Definition: EnvCheck.cpp:24
void timeThis(const F &f, const char *const name)
Definition: Timer.h:108
static unsigned getTID()
Definition: ThreadPool.h:204
Definition: PerThreadStorage.h:88
void on_each(FunctionTy &&fn, const Args &...args)
Low-level parallel loop.
Definition: Loops.h:86
void profilePapi(const F &func, const char *region)
Definition: Profile.h:220
void gWarn(Args &&...args)
Prints a warning string from a sequence of things.
Definition: gIO.h:63