forked from intel/pti-gpu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcl_api_collector.h
205 lines (173 loc) · 6.11 KB
/
cl_api_collector.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//==============================================================
// Copyright (C) Intel Corporation
//
// SPDX-License-Identifier: MIT
// =============================================================
#ifndef PTI_SAMPLES_CL_HOT_FUNCTIONS_CL_API_COLLECTOR_H_
#define PTI_SAMPLES_CL_HOT_FUNCTIONS_CL_API_COLLECTOR_H_
#include <chrono>
#include <iomanip>
#include <iostream>
#include <map>
#include <mutex>
#include <set>
#include "cl_api_tracer.h"
#include "cl_utils.h"
struct ClFunction {
uint64_t total_time;
uint64_t min_time;
uint64_t max_time;
uint64_t call_count;
bool operator>(const ClFunction& r) const {
if (total_time != r.total_time) {
return total_time > r.total_time;
}
return call_count > r.call_count;
}
bool operator!=(const ClFunction& r) const {
if (total_time == r.total_time) {
return call_count != r.call_count;
}
return true;
}
};
using ClFunctionInfoMap = std::map<std::string, ClFunction>;
class ClApiCollector {
public: // User Interface
static ClApiCollector* Create(cl_device_id device) {
PTI_ASSERT(device != nullptr);
ClApiCollector* collector = new ClApiCollector();
PTI_ASSERT(collector != nullptr);
ClApiTracer* tracer = new ClApiTracer(device, Callback, collector);
if (tracer == nullptr || !tracer->IsValid()) {
std::cerr << "[WARNING] Unable to create OpenCL tracer " <<
"for target device" << std::endl;
if (tracer != nullptr) {
delete tracer;
}
delete collector;
return nullptr;
}
collector->EnableTracing(tracer);
return collector;
}
~ClApiCollector() {
if (tracer_ != nullptr) {
delete tracer_;
}
}
void DisableTracing() {
PTI_ASSERT(tracer_ != nullptr);
bool disabled = tracer_->Disable();
PTI_ASSERT(disabled);
}
const ClFunctionInfoMap& GetFunctionInfoMap() const {
return function_info_map_;
}
ClApiCollector(const ClApiCollector& copy) = delete;
ClApiCollector& operator=(const ClApiCollector& copy) = delete;
static void PrintFunctionsTable(const ClFunctionInfoMap& function_info_map) {
std::set< std::pair<std::string, ClFunction>,
utils::Comparator > sorted_list(
function_info_map.begin(), function_info_map.end());
uint64_t total_duration = 0;
size_t max_name_length = kFunctionLength;
for (auto& value : sorted_list) {
total_duration += value.second.total_time;
if (value.first.size() > max_name_length) {
max_name_length = value.first.size();
}
}
if (total_duration == 0) {
return;
}
std::cerr << std::setw(max_name_length) << "Function" << "," <<
std::setw(kCallsLength) << "Calls" << "," <<
std::setw(kTimeLength) << "Time (ns)" << "," <<
std::setw(kPercentLength) << "Time (%)" << "," <<
std::setw(kTimeLength) << "Average (ns)" << "," <<
std::setw(kTimeLength) << "Min (ns)" << "," <<
std::setw(kTimeLength) << "Max (ns)" << std::endl;
for (auto& value : sorted_list) {
const std::string& function = value.first;
uint64_t call_count = value.second.call_count;
uint64_t duration = value.second.total_time;
uint64_t avg_duration = duration / call_count;
uint64_t min_duration = value.second.min_time;
uint64_t max_duration = value.second.max_time;
float percent_duration = 100.0f * duration / total_duration;
std::cerr << std::setw(max_name_length) << function << "," <<
std::setw(kCallsLength) << call_count << "," <<
std::setw(kTimeLength) << duration << "," <<
std::setw(kPercentLength) << std::setprecision(2) <<
std::fixed << percent_duration << "," <<
std::setw(kTimeLength) << avg_duration << "," <<
std::setw(kTimeLength) << min_duration << "," <<
std::setw(kTimeLength) << max_duration << std::endl;
}
}
private: // Implementation Details
ClApiCollector() {}
void EnableTracing(ClApiTracer* tracer) {
PTI_ASSERT(tracer != nullptr);
tracer_ = tracer;
for (int id = 0; id < CL_FUNCTION_COUNT; ++id) {
bool set = tracer_->SetTracingFunction(static_cast<cl_function_id>(id));
PTI_ASSERT(set);
}
bool enabled = tracer_->Enable();
PTI_ASSERT(enabled);
}
uint64_t GetTimestamp() const {
std::chrono::duration<uint64_t, std::nano> timestamp =
std::chrono::steady_clock::now() - base_time_;
return timestamp.count();
}
void AddFunctionTime(const std::string& name, uint64_t time) {
const std::lock_guard<std::mutex> lock(lock_);
if (function_info_map_.count(name) == 0) {
function_info_map_[name] = {time, time, time, 1};
} else {
ClFunction& function = function_info_map_[name];
function.total_time += time;
if (time < function.min_time) {
function.min_time = time;
}
if (time > function.max_time) {
function.max_time = time;
}
++function.call_count;
}
}
private: // Callbacks
static void Callback(
cl_function_id function,
cl_callback_data* callback_data,
void* user_data) {
ClApiCollector* collector = reinterpret_cast<ClApiCollector*>(user_data);
PTI_ASSERT(collector != nullptr);
PTI_ASSERT(callback_data != nullptr);
PTI_ASSERT(callback_data->correlationData != nullptr);
if (callback_data->site == CL_CALLBACK_SITE_ENTER) {
uint64_t& start_time = *reinterpret_cast<uint64_t*>(
callback_data->correlationData);
start_time = collector->GetTimestamp();
} else {
uint64_t end_time = collector->GetTimestamp();
uint64_t& start_time = *reinterpret_cast<uint64_t*>(
callback_data->correlationData);
collector->AddFunctionTime(
callback_data->functionName, end_time - start_time);
}
}
private: // Data
ClApiTracer* tracer_ = nullptr;
std::chrono::time_point<std::chrono::steady_clock> base_time_;
std::mutex lock_;
ClFunctionInfoMap function_info_map_;
static const uint32_t kFunctionLength = 10;
static const uint32_t kCallsLength = 12;
static const uint32_t kTimeLength = 20;
static const uint32_t kPercentLength = 10;
};
#endif // PTI_SAMPLES_CL_HOT_FUNCTIONS_CL_API_COLLECTOR_H_