#include <mutex>
#include "common/utils.hpp"
#include "common/verbose.hpp"
#include "cpu/platform.hpp"
#ifndef DNNL_ENABLE_JIT_PROFILING
#define DNNL_ENABLE_JIT_PROFILING 1
#endif
#ifndef DNNL_ENABLE_JIT_DUMP
#define DNNL_ENABLE_JIT_DUMP 1
#endif
#if DNNL_ENABLE_JIT_PROFILING
#include "ittnotify/jitprofiling.h"
#ifdef __linux__
#include "cpu/jit_utils/linux_perf/linux_perf.hpp"
#endif
#endif
namespace dnnl {
namespace impl {
namespace cpu {
namespace jit_utils {
#define DUMP_BASE_FNAME "dnnl_dump_cpu_"
#define DUMP_EXT_FNAME ".bin"
#define MAX_FNAME_LEN 256
#define MAX_CODENAME_LEN \
(MAX_FNAME_LEN - sizeof(DUMP_BASE_FNAME) - sizeof(DUMP_EXT_FNAME))
void dump_jit_code(const void *code, size_t code_size, const char *code_name) {
#if DNNL_ENABLE_JIT_DUMP
if (code && get_jit_dump()) {
char fname[MAX_FNAME_LEN + 1];
snprintf(fname, MAX_FNAME_LEN, DUMP_BASE_FNAME "%s" DUMP_EXT_FNAME,
code_name);
FILE *fp = fopen(fname, "wb+");
if (fp) {
size_t unused = fwrite(code, code_size, 1, fp);
UNUSED(unused);
fclose(fp);
}
}
#else
UNUSED(code);
UNUSED(code_size);
UNUSED(code_name);
#endif
}
void register_jit_code_vtune(const void *code, size_t code_size,
const char *code_name, const char *source_file_name) {
#if DNNL_ENABLE_JIT_PROFILING
unsigned flags = get_jit_profiling_flags();
#if DNNL_X64
if ((flags & DNNL_JIT_PROFILE_VTUNE)
&& iJIT_IsProfilingActive() == iJIT_SAMPLING_ON) {
auto jmethod = iJIT_Method_Load();
jmethod.method_id = iJIT_GetNewMethodID(); jmethod.method_name = (char *)code_name; jmethod.class_file_name = nullptr;
jmethod.source_file_name
= (char *)source_file_name; jmethod.method_load_address = (void *)code;
jmethod.method_size = (unsigned int)code_size;
iJIT_NotifyEvent(
iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void *)&jmethod);
}
#else
if (flags & DNNL_JIT_PROFILE_VTUNE)
VWARN(primitive, jit_profiling,
"VTune Profiler integration is not supported");
#endif
#else
UNUSED(code);
UNUSED(code_size);
UNUSED(code_name);
UNUSED(source_file_name);
#endif
}
void register_jit_code_linux_perf(const void *code, size_t code_size,
const char *code_name, const char *source_file_name) {
#if DNNL_ENABLE_JIT_PROFILING && defined(__linux__)
unsigned flags = get_jit_profiling_flags();
if (flags & DNNL_JIT_PROFILE_LINUX_JITDUMP)
linux_perf_jitdump_record_code_load(code, code_size, code_name);
if (flags & DNNL_JIT_PROFILE_LINUX_PERFMAP)
linux_perf_perfmap_record_code_load(code, code_size, code_name);
#else
UNUSED(code);
UNUSED(code_size);
UNUSED(code_name);
#endif
UNUSED(source_file_name);
}
void register_jit_code(const void *code, size_t code_size,
const char *code_name, const char *source_file_name) {
#if DNNL_ENABLE_JIT_PROFILING || DNNL_ENABLE_JIT_DUMP
static std::mutex m;
static int unique_id = 0;
std::lock_guard<std::mutex> guard(m);
char unique_code_name[MAX_CODENAME_LEN + 1];
snprintf(unique_code_name, MAX_CODENAME_LEN, "%s.%d", code_name,
unique_id++);
dump_jit_code(code, code_size, unique_code_name);
register_jit_code_vtune(code, code_size, code_name, source_file_name);
register_jit_code_linux_perf(
code, code_size, unique_code_name, source_file_name);
#else
UNUSED(code);
UNUSED(code_size);
UNUSED(code_name);
UNUSED(source_file_name);
#endif
}
#undef DUMP_BASE_FNAME
#undef DUMP_EXT_FNAME
#undef MAX_FNAME_LEN
#undef MAX_CODENAME_LEN
} } } }