22#include <unordered_map>
36 std::unordered_map<int32_t, struct sigaction>
oldActions;
49 static std::mutex initMutex;
51 std::lock_guard<std::mutex> guard(initMutex);
53 GPUFatal(
"Error handlers for debug dumps already set, cannot set them again");
55 mDebugData = std::make_unique<debugInternal>();
59 struct sigaction sa, oldsa;
60 memset(&sa, 0,
sizeof(sa));
62 sa.sa_flags = SA_SIGINFO;
65 for (uint32_t
i = 0;
i <
sizeof(
mask) * 8;
i++) {
66 if (
mask & (1 <<
i)) {
67 if (sigaction(
i, &sa, &oldsa)) {
68 GPUFatal(
"Error installing signal handler for error dump on signal %d",
i);
75 mDebugData->signalCallback = [
this, &oldActions =
mDebugData->oldActions, myAction = std::move(sa)](int32_t signal, siginfo_t* info,
void* ucontext) {
76 static std::mutex callbackMutex;
77 std::lock_guard<std::mutex> guard(callbackMutex);
79 GPUInfo(
"Running debug callback for signal %d", signal);
85 sigaction(signal, &oldActions[signal],
nullptr);
87 mDebugData->reinstallCallback = [signal, myAction]() { sigaction(signal, &myAction,
nullptr); };
101 if (sigaction(it.first, &it.second,
nullptr)) {
102 GPUFatal(
"Error restoring signal handler for signal %d", it.first);
126 std::size_t total_size = 0;
127 std::size_t subfolder_count = 0;
129 if (!std::filesystem::exists(target_dir) || !std::filesystem::is_directory(target_dir)) {
130 GPUError(
"Invalid debugOnFailureDirectory %s",
GetProcessingSettings().debugOnFailureDirectory.c_str());
134 for (
const auto&
entry : std::filesystem::directory_iterator(target_dir)) {
135 if (
entry.is_directory()) {
138 for (
const auto& subentry : std::filesystem::directory_iterator(
entry.path())) {
139 if (subentry.is_regular_file()) {
141 auto size = std::filesystem::file_size(subentry.path(), ec);
151 GPUError(
"Cannot store debug dump files, target storage exceeded: %zu dumps, %zu bytes", subfolder_count, total_size);
155 auto currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
156 std::ostringstream dateTime;
157 dateTime << std::put_time(std::localtime(¤tTime),
"%Y-%m-%d_%H-%M-%S");
162 if (attempt++ >= 512) {
163 GPUError(
"Error creating debug dump folder");
169 bool created = std::filesystem::create_directory(outname, ec);
170 if (!ec && created) {
175 GPUInfo(
"Debug dump to %s", outname.c_str());
184 GPUInfo(
"Running triggered debug callback");
193GPUReconstructionCPU::debugWriter::debugWriter(std::string filenameCSV,
bool markdown, uint32_t statNEvents) : mMarkdown{markdown}, mStatNEvents{statNEvents}
195 if (!filenameCSV.empty()) {
196 streamCSV.open(filenameCSV, std::ios::out | std::ios::app);
200void GPUReconstructionCPU::debugWriter::header()
202 if (streamCSV.is_open() && !streamCSV.tellp()) {
203 streamCSV <<
"type,count,name,gpu (us),cpu (us),cpu/total,total (us),GB/s,bytes,bytes/call\n";
207 std::cout <<
"| | count | name | gpu (us) | cpu (us) | cpu/tot | tot (us) | GB/s | bytes | bytes/call |\n";
208 std::cout <<
"|---|--------|-------------------------------------------|-----------|-----------|---------|-----------|-----------|---------------|---------------|\n";
212void GPUReconstructionCPU::debugWriter::row(
char type, uint32_t
count, std::string
name,
double gpu_time,
double cpu_time,
double total_time, std::size_t memSize, std::string nEventReport)
214 double scale = 1000000.0 / mStatNEvents;
216 if (streamCSV.is_open()) {
217 streamCSV <<
type <<
",";
221 streamCSV <<
"," <<
name <<
",";
222 if (gpu_time != -1.0) {
223 streamCSV << std::format(
"{:.0f}", gpu_time * scale);
226 if (cpu_time != -1.0) {
227 streamCSV << std::format(
"{:.0f}", cpu_time * scale);
230 if (cpu_time != -1.0 && total_time != -1.0) {
231 streamCSV << std::format(
"{:.2f}", cpu_time / total_time);
234 if (total_time != -1.0) {
235 streamCSV << std::format(
"{:.0f}", total_time * scale);
238 if (memSize != 0 &&
count != 0) {
239 streamCSV << std::format(
"{:.3f},{},{}", memSize / gpu_time * 1e-9, memSize / mStatNEvents, memSize / mStatNEvents /
count);
243 streamCSV << std::endl;
247 std::cout <<
"| " <<
type <<
" | ";
249 std::cout << std::format(
"{:6} |",
count);
253 std::cout << std::format(
" {:42}|",
name);
254 if (gpu_time != -1.0) {
255 std::cout << std::format(
"{:10.0f} |", gpu_time * scale);
259 if (cpu_time != -1.0) {
260 std::cout << std::format(
"{:10.0f} |", cpu_time * scale);
264 if (cpu_time != -1.0 && total_time != -1.0) {
265 std::cout << std::format(
"{:8.2f} |", cpu_time / total_time);
269 if (total_time != -1.0) {
270 std::cout << std::format(
"{:10.0f} |", total_time * scale);
274 if (memSize != 0 &&
count != 0) {
275 std::cout << std::format(
"{:10.3f} |{:14} |{:14} |", memSize / gpu_time * 1e-9, memSize / mStatNEvents, memSize / mStatNEvents /
count);
277 std::cout <<
" | | |";
279 std::cout << std::endl;
281 if (
name.substr(0, 3) ==
"GPU") {
282 char bandwidth[256] =
"";
283 if (memSize && mStatNEvents && gpu_time != 0.0) {
284 snprintf(bandwidth, 256,
" (%8.3f GB/s - %'14zu bytes - %'14zu per call)", memSize / gpu_time * 1e-9, memSize / mStatNEvents, memSize / mStatNEvents /
count);
286 printf(
"Execution Time: Task (%c %8ux): %50s Time: %'10.0f us%s\n",
type,
count,
name.c_str(), gpu_time * scale, bandwidth);
287 }
else if (
name.substr(0, 3) ==
"TPC") {
288 std::size_t
n =
name.find(
'(');
289 std::string basename =
name.substr(0,
n - 1);
290 std::string postfix =
name.substr(
n + 1,
name.size() -
n - 2);
291 if (total_time != -1.0) {
292 printf(
"Execution Time: Step : %11s %38s Time: %'10.0f us %64s ( Total Time : %'14.0f us, CPU Time : %'14.0f us, %'7.2fx )\n", postfix.c_str(),
293 basename.c_str(), gpu_time * scale,
"", total_time * scale, cpu_time * scale, cpu_time / total_time);
295 printf(
"Execution Time: Step (D %8ux): %11s %38s Time: %'10.0f us (%8.3f GB/s - %'14zu bytes - %'14zu per call)\n",
count, postfix.c_str(), basename.c_str(), gpu_time * scale,
296 memSize / gpu_time * 1e-9, memSize / mStatNEvents, memSize / mStatNEvents /
count);
298 }
else if (
name ==
"Prepare") {
299 printf(
"Execution Time: General Step : %50s Time: %'10.0f us\n",
name.c_str(), gpu_time * scale);
300 }
else if (
name ==
"Wall") {
301 if (gpu_time != -1.0) {
302 printf(
"Execution Time: Total : %50s Time: %'10.0f us%s\n",
"Total Kernel", gpu_time * scale, nEventReport.c_str());
304 printf(
"Execution Time: Total : %50s Time: %'10.0f us ( CPU Time : %'10.0f us, %7.2fx ) %s\n",
"Total Wall", total_time * scale, cpu_time * scale, cpu_time / total_time, nEventReport.c_str());
GPUReconstruction * mMaster
std::string getDebugFolder(const std::string &prefix="")
void setDebugDumpCallback(std::function< void()> &&callback=std::function< void()>(nullptr))
static std::unique_ptr< debugInternal > mDebugData
const GPUSettingsProcessing & GetProcessingSettings() const
GLuint const GLchar * name
GLint GLint GLsizei GLint GLenum GLenum type
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
std::string to_string(gsl::span< T, Size > span)
std::function< void()> debugCallback
std::function< void(int32_t, siginfo_t *, void *)> signalCallback
static void globalCallback(int32_t signal, siginfo_t *info, void *ucontext)
std::unordered_map< int32_t, struct sigaction > oldActions
std::function< void()> reinstallCallback