4
4
// PGO functions which should know whether the code in the alternatives op is
5
5
// GPU code - we can add an attrib to the alternatives op for that
6
6
7
+ #include < cstdlib>
7
8
#include < ctime>
8
9
#include < filesystem>
9
10
#include < fstream>
10
11
#include < iostream>
11
12
#include < map>
12
13
#include < mutex>
14
+ #include < numeric>
15
+ #include < vector>
13
16
14
17
extern " C" int32_t mgpurtDeviceSynchronizeErr (void );
15
18
@@ -26,26 +29,38 @@ class PGOState {
26
29
struct timespec start_clock;
27
30
};
28
31
32
+ struct Logger {
33
+ std::map<std::string, std::vector<double >> timings;
34
+ ~Logger () { PGOState::writeResults (); }
35
+ };
36
+
29
37
inline static int alternative;
30
38
inline static std::string dirname;
31
39
inline thread_local static std::mutex mutex;
32
40
inline thread_local static std::map<std::string, State *> states;
41
+ inline static Logger logger;
33
42
34
- std::string kernelId ;
43
+ const char *kernelId_c ;
35
44
int totalAlternatives;
36
45
37
- PGOState (const char *kernelId_c, int totalAlternatives)
38
- : totalAlternatives(totalAlternatives) {
39
- kernelId = kernelId_c;
46
+ std::string getKernelId () {
47
+ std::string kernelId = kernelId_c;
40
48
for (char &c : kernelId)
41
49
if (c == ' /' )
42
50
c = ' +' ;
51
+ return kernelId;
52
+ }
53
+
54
+ PGOState (const char *kernelId_c, int totalAlternatives)
55
+ : totalAlternatives(totalAlternatives) {
56
+ this ->kernelId_c = kernelId_c;
43
57
}
44
58
void end () {
45
59
struct timespec end_clock;
46
60
mgpurtDeviceSynchronizeErr ();
47
61
clock_gettime (CLOCK_MONOTONIC, &end_clock);
48
62
63
+ auto kernelId = getKernelId ();
49
64
std::unique_lock<std::mutex> lock (mutex);
50
65
if (states.count (kernelId) == 0 ) {
51
66
std::cerr << " No kernel with id " << kernelId << " running" << std::endl;
@@ -59,21 +74,16 @@ class PGOState {
59
74
double elapsed =
60
75
(tmp_clock.tv_sec + ((double )tmp_clock.tv_nsec ) * .000000001 );
61
76
62
- // Only write to file if we are profiling a valid alternative
63
- if (0 <= alternative && alternative < totalAlternatives) {
64
- // TODO error handling
65
- std::ofstream ofile;
66
- ofile.open (std::string (dirname) + " /" + kernelId,
67
- std::ios::out | std::ios::app);
68
- ofile << alternative << " " << elapsed << std::endl;
69
- ofile.close ();
70
- }
77
+ if (states.count (kernelId) == 0 )
78
+ logger.timings [kernelId] = {};
79
+ logger.timings [kernelId].push_back (elapsed);
71
80
72
81
delete state;
73
82
states.erase (states.find (kernelId));
74
83
}
75
84
76
85
void start () {
86
+ auto kernelId = getKernelId ();
77
87
std::unique_lock<std::mutex> lock (mutex);
78
88
State *state = new State ();
79
89
if (states.count (kernelId) == 1 ) {
@@ -87,6 +97,21 @@ class PGOState {
87
97
clock_gettime (CLOCK_MONOTONIC, &state->start_clock );
88
98
}
89
99
100
+ static void writeResults () {
101
+ // Only write to file if we are profiling a valid alternative
102
+ for (auto &pair : logger.timings ) {
103
+ auto &kernelId = std::get<0 >(pair);
104
+ auto &timings = std::get<1 >(pair);
105
+ auto elapsed = std::accumulate (timings.begin (), timings.end (), 0 .0f );
106
+ // TODO error handling
107
+ std::ofstream ofile;
108
+ ofile.open (std::string (dirname) + " /" + kernelId,
109
+ std::ios::out | std::ios::app);
110
+ ofile << alternative << " " << elapsed << std::endl;
111
+ ofile.close ();
112
+ }
113
+ }
114
+
90
115
int getAlternative () {
91
116
static int init = [&] {
92
117
if (char *i = getenv (POLYGEIST_PGO_ALTERNATIVE_ENV_VAR)) {
@@ -102,12 +127,10 @@ class PGOState {
102
127
this ->dirname = POLYGEIST_PGO_DEFAULT_DATA_DIR;
103
128
}
104
129
std::filesystem::create_directories (dirname);
130
+
105
131
return 0 ;
106
132
}();
107
- if (0 <= alternative && alternative < totalAlternatives)
108
- return alternative;
109
- else
110
- return 0 ;
133
+ return alternative % totalAlternatives;
111
134
}
112
135
113
136
~PGOState () {}
0 commit comments