[GPU] Add per iteration performance profiling mode (#18637)
This commit is contained in:
1 parent
acbac2f560
commit
7df8d1ca2d
7 files changed
+42
-19
No files matched your search
@@ -249,6 +249,10 @@ public:
|
||||
|
||||
ShapePredictor& get_shape_predictor() { return *_shape_predictor; }
|
||||
|
||||
#ifdef GPU_DEBUG_CONFIG
|
||||
int64_t get_current_iteration_num() { return iteration; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
using output_chains_map = std::map<primitive_id, std::vector<std::shared_ptr<primitive_inst>>>;
|
||||
uint32_t net_id = 0;
|
||||
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
int disable_onednn; // Disable onednn for discrete GPU (no effect for integrated GPU)
|
||||
int disable_onednn_opt_post_ops; // Disable onednn optimize post operators
|
||||
std::string dump_profiling_data; // Enables dump of extended performance profiling to specified dir
|
||||
int dump_profiling_data_per_iter; // Enables dump of extended performance profiling to specified dir for each iteration
|
||||
std::string dump_graphs; // Dump optimized graph
|
||||
std::string dump_sources; // Dump opencl sources
|
||||
std::string dump_layers_path; // Enable dumping intermediate buffers and set the dest path
|
||||
|
||||
@@ -119,6 +119,7 @@ struct perf_counter_key {
|
||||
std::vector<layout> output_layouts;
|
||||
std::string impl_name;
|
||||
pipeline_stage stage;
|
||||
int64_t iteration_num;
|
||||
bool cache_hit;
|
||||
};
|
||||
|
||||
@@ -127,6 +128,7 @@ struct perf_counter_hash {
|
||||
size_t seed = 0;
|
||||
seed = hash_combine(seed, static_cast<std::underlying_type<instrumentation::pipeline_stage>::type>(k.stage));
|
||||
seed = hash_combine(seed, static_cast<int>(k.cache_hit));
|
||||
seed = hash_combine(seed, k.iteration_num);
|
||||
for (auto& layout : k.network_input_layouts) {
|
||||
for (auto& d : layout.get_shape()) {
|
||||
seed = hash_combine(seed, d);
|
||||
@@ -154,6 +156,7 @@ public:
|
||||
, _obj(obj)
|
||||
, _stage(stage) {
|
||||
GPU_DEBUG_IF(profiling_enabled) {
|
||||
_per_iter_mode = cldnn::debug_configuration::get_instance()->dump_profiling_data_per_iter != 0;
|
||||
_start = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
}
|
||||
@@ -167,7 +170,7 @@ public:
|
||||
auto custom_stage_duration = std::chrono::duration_cast<us>(custom_duration).count();
|
||||
auto total_duration = custom_stage_duration == 0 ? stage_duration
|
||||
: custom_stage_duration;
|
||||
_obj.add_profiling_data(_stage, cache_hit, total_duration);
|
||||
_obj.add_profiling_data(_stage, cache_hit, total_duration, _per_iter_mode);
|
||||
}
|
||||
}
|
||||
void set_cache_hit(bool val = true) { cache_hit = val; }
|
||||
@@ -180,6 +183,7 @@ private:
|
||||
std::chrono::nanoseconds custom_duration = {};
|
||||
ProfiledObjectType& _obj;
|
||||
instrumentation::pipeline_stage _stage;
|
||||
bool _per_iter_mode = false;
|
||||
bool cache_hit = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ public:
|
||||
std::unordered_map<primitive_id, std::shared_ptr<primitive_inst>> const& primitives);
|
||||
std::string get_implementation_name() const;
|
||||
|
||||
void add_profiling_data(instrumentation::pipeline_stage stage, bool cache_hit, int64_t time);
|
||||
void add_profiling_data(instrumentation::pipeline_stage stage, bool cache_hit, int64_t time, bool per_iter_mode = false);
|
||||
const std::unordered_map<size_t, std::tuple<int64_t, size_t>>& get_profiling_data() const { return _profiling_data; }
|
||||
const std::unordered_map<size_t, instrumentation::perf_counter_key>& get_profiling_info() const { return _profiling_info; }
|
||||
|
||||
|
||||
@@ -75,7 +75,9 @@ void dump_perf_data_raw(std::string dump_path, const std::list<std::shared_ptr<p
|
||||
return s.str();
|
||||
};
|
||||
|
||||
const std::string perf_raw_csv_header = "prim_id,prim_type,stage,net_in_shapes,in_shapes,out_shapes,impl,iters,time_usec\n";
|
||||
const bool per_iter_mode = cldnn::debug_configuration::get_instance()->dump_profiling_data_per_iter != 0;
|
||||
const std::string perf_raw_csv_header = per_iter_mode ? "prim_id,prim_type,stage,net_in_shapes,in_shapes,out_shapes,impl,iter,time_usec\n"
|
||||
: "prim_id,prim_type,stage,net_in_shapes,in_shapes,out_shapes,impl,iters,time_usec\n";
|
||||
std::ofstream of(dump_path);
|
||||
if (of.is_open()) {
|
||||
of << perf_raw_csv_header;
|
||||
@@ -114,8 +116,8 @@ void dump_perf_data_raw(std::string dump_path, const std::list<std::shared_ptr<p
|
||||
auto& key = perf_info.at(hash);
|
||||
auto& entry = perf_data.at(hash);
|
||||
auto& time = std::get<0>(entry);
|
||||
auto& num_iters = std::get<1>(entry);
|
||||
int64_t time_avg = time / num_iters;
|
||||
auto num_iters = per_iter_mode ? key.iteration_num : std::get<1>(entry);
|
||||
int64_t time_avg = per_iter_mode ? time : time / num_iters;
|
||||
std::string net_in_l_str = layouts_to_str(key.network_input_layouts);
|
||||
std::string in_l_str = layouts_to_str(key.input_layouts);
|
||||
std::string out_l_str = layouts_to_str(key.output_layouts);
|
||||
@@ -246,7 +248,7 @@ void dump<uint32_t>(memory::ptr mem, stream& stream, std::ofstream& file_stream,
|
||||
}
|
||||
}
|
||||
|
||||
void log_memory_to_file(memory::ptr mem, stream& stream, std::string layerName, bool dump_raw) {
|
||||
void log_memory_to_file(memory::ptr mem, layout data_layout, stream& stream, std::string layerName, bool dump_raw) {
|
||||
std::cout << "Dump " << (dump_raw ? "raw " : "") << layerName << std::endl;
|
||||
GPU_DEBUG_GET_INSTANCE(debug_config);
|
||||
std::string filename = debug_config->get_name_for_dump(layerName);
|
||||
@@ -257,21 +259,24 @@ void log_memory_to_file(memory::ptr mem, stream& stream, std::string layerName,
|
||||
return;
|
||||
}
|
||||
|
||||
auto mem_dt = mem->get_layout().data_type;
|
||||
// Reinterpret buffer to represent actual data layout
|
||||
auto actual_mem = mem->get_engine()->reinterpret_buffer(*mem, data_layout);
|
||||
|
||||
auto mem_dt = actual_mem->get_layout().data_type;
|
||||
if (mem_dt == cldnn::data_types::f32)
|
||||
dump<float>(mem, stream, file_stream, dump_raw);
|
||||
dump<float>(actual_mem, stream, file_stream, dump_raw);
|
||||
else if (mem_dt == cldnn::data_types::f16)
|
||||
dump<half_t>(mem, stream, file_stream, dump_raw);
|
||||
dump<half_t>(actual_mem, stream, file_stream, dump_raw);
|
||||
else if (mem_dt == cldnn::data_types::bin)
|
||||
dump<uint32_t>(mem, stream, file_stream, dump_raw);
|
||||
dump<uint32_t>(actual_mem, stream, file_stream, dump_raw);
|
||||
else if (mem_dt == cldnn::data_types::i64)
|
||||
dump<int64_t>(mem, stream, file_stream, dump_raw);
|
||||
dump<int64_t>(actual_mem, stream, file_stream, dump_raw);
|
||||
else if (mem_dt == cldnn::data_types::i32)
|
||||
dump<int32_t>(mem, stream, file_stream, dump_raw);
|
||||
dump<int32_t>(actual_mem, stream, file_stream, dump_raw);
|
||||
else if (mem_dt == cldnn::data_types::i8)
|
||||
dump<int8_t>(mem, stream, file_stream, dump_raw);
|
||||
dump<int8_t>(actual_mem, stream, file_stream, dump_raw);
|
||||
else if (mem_dt == cldnn::data_types::u8)
|
||||
dump<uint8_t>(mem, stream, file_stream, dump_raw);
|
||||
dump<uint8_t>(actual_mem, stream, file_stream, dump_raw);
|
||||
}
|
||||
|
||||
void wait_for_the_turn() {
|
||||
@@ -294,7 +299,7 @@ void wait_for_the_turn() {
|
||||
|
||||
#else
|
||||
void dump_perf_data_raw(std::string, const std::list<std::shared_ptr<primitive_inst>>&) {}
|
||||
void log_memory_to_file(memory::ptr, stream&, std::string, bool dump_raw) {}
|
||||
void log_memory_to_file(memory::ptr, layout, stream&, std::string, bool dump_raw) {}
|
||||
void wait_for_the_turn() {}
|
||||
#endif
|
||||
} // namespace
|
||||
@@ -1337,6 +1342,7 @@ void network::execute_impl(const std::vector<event::ptr>& events) {
|
||||
debug_str_for_bin_load += (filename + ",");
|
||||
} else {
|
||||
log_memory_to_file(input_mem,
|
||||
inst->get_input_layout(i),
|
||||
get_stream(),
|
||||
name,
|
||||
debug_config->dump_layers_raw);
|
||||
@@ -1383,7 +1389,7 @@ void network::execute_impl(const std::vector<event::ptr>& events) {
|
||||
debug_str_for_bin_load += (filename + ",");
|
||||
} else {
|
||||
// Text dump
|
||||
log_memory_to_file(output_mem, get_stream(), name, debug_config->dump_layers_raw);
|
||||
log_memory_to_file(output_mem, inst->get_output_layout(i), get_stream(), name, debug_config->dump_layers_raw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1504,13 +1504,18 @@ bool primitive_inst::is_valid_fusion() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void primitive_inst::add_profiling_data(instrumentation::pipeline_stage stage, bool cache_hit, int64_t time) {
|
||||
void primitive_inst::add_profiling_data(instrumentation::pipeline_stage stage, bool cache_hit, int64_t time, bool per_iter_mode) {
|
||||
instrumentation::perf_counter_key key {
|
||||
_network.get_input_layouts(),
|
||||
_impl_params->input_layouts,
|
||||
_impl_params->output_layouts,
|
||||
get_implementation_name(),
|
||||
stage,
|
||||
#ifdef GPU_DEBUG_CONFIG
|
||||
per_iter_mode ? get_network().get_current_iteration_num() : 0,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
cache_hit
|
||||
};
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ static void print_help_messages() {
|
||||
message_list.emplace_back("OV_GPU_DisableOnednn", "Disable onednn for discrete GPU (no effect for integrated GPU)");
|
||||
message_list.emplace_back("OV_GPU_DisableOnednnOptPostOps", "Disable onednn optimize post operators");
|
||||
message_list.emplace_back("OV_GPU_DumpProfilingData", "Enables dump of extended profiling information to specified directory."
|
||||
" Please use OV_GPU_DumpProfilingDataPerIter=1 env variable to collect performance per iteration."
|
||||
" Note: Performance impact may be significant as this option enforces host side sync after each primitive");
|
||||
message_list.emplace_back("OV_GPU_DumpGraphs", "Dump optimized graph");
|
||||
message_list.emplace_back("OV_GPU_DumpSources", "Dump opencl sources");
|
||||
@@ -142,9 +143,9 @@ static void print_help_messages() {
|
||||
message_list.emplace_back("OV_GPU_DisableRuntimeSkipReorder", "Disable runtime skip reorder.");
|
||||
message_list.emplace_back("OV_GPU_DisablePrimitiveFusing", "Disable primitive fusing");
|
||||
message_list.emplace_back("OV_GPU_DumpIteration", "Dump n-th execution of network, separated by space.");
|
||||
message_list.emplace_back("OV_GPU_MemPreallocationOptions", "Controls buffer pre-allocation feature. Expects 4 values separated by space in"
|
||||
message_list.emplace_back("OV_GPU_MemPreallocationOptions", "Controls buffer pre-allocation feature. Expects 4 values separated by space in "
|
||||
"the following order: number of iterations for pre-allocation(int), max size of single iteration in bytes(int), "
|
||||
"max per-dim allowed diff(int), unconditional buffers preallocation ratio(float). For example for disabling memory"
|
||||
"max per-dim allowed diff(int), unconditional buffers preallocation ratio(float). For example for disabling memory "
|
||||
"preallocation at all, you can use OV_GPU_MemPreallocationOptions='0 0 0 1.0'");
|
||||
message_list.emplace_back("OV_GPU_LoadDumpRawBinary",
|
||||
"Specified layers which are loading dumped binary files generated by OV_GPU_DumpLayersRawBinary debug-config."
|
||||
@@ -176,6 +177,7 @@ debug_configuration::debug_configuration()
|
||||
, disable_onednn(0)
|
||||
, disable_onednn_opt_post_ops(0)
|
||||
, dump_profiling_data(std::string(""))
|
||||
, dump_profiling_data_per_iter(0)
|
||||
, dump_graphs(std::string())
|
||||
, dump_sources(std::string())
|
||||
, dump_layers_path(std::string())
|
||||
@@ -217,6 +219,7 @@ debug_configuration::debug_configuration()
|
||||
get_gpu_debug_env_var("DisableOnednn", disable_onednn);
|
||||
get_gpu_debug_env_var("DisableOnednnOptPostOps", disable_onednn_opt_post_ops);
|
||||
get_gpu_debug_env_var("DumpProfilingData", dump_profiling_data);
|
||||
get_gpu_debug_env_var("DumpProfilingDataPerIter", dump_profiling_data_per_iter);
|
||||
get_gpu_debug_env_var("DryRunPath", dry_run_path);
|
||||
get_gpu_debug_env_var("DumpRuntimeMemoryPool", dump_runtime_memory_pool);
|
||||
get_gpu_debug_env_var("BaseBatchForMemEstimation", base_batch_for_memory_estimation);
|
||||
|
||||
Reference in new issue
Block a user