diff --git a/include/nvtop/extract_gpuinfo_common.h b/include/nvtop/extract_gpuinfo_common.h index c0bad5a..9e4d1c9 100644 --- a/include/nvtop/extract_gpuinfo_common.h +++ b/include/nvtop/extract_gpuinfo_common.h @@ -105,6 +105,7 @@ enum gpuinfo_dynamic_info_valid { gpuinfo_gpu_temp_valid, gpuinfo_power_draw_valid, gpuinfo_power_draw_max_valid, + gpuinfo_effective_load_rate_valid, gpuinfo_multi_instance_mode_valid, gpuinfo_dynamic_info_count, }; @@ -116,6 +117,7 @@ struct gpuinfo_dynamic_info { unsigned int mem_clock_speed_max; // Maximum clock speed in MHz unsigned int gpu_util_rate; // GPU utilization rate in % unsigned int mem_util_rate; // MEM utilization rate in % + unsigned int effective_load_rate; // Effective load rate in % unsigned int encoder_rate; // Encoder utilization rate in % unsigned int decoder_rate; // Decoder utilization rate in % unsigned long long total_memory; // Total memory (bytes) diff --git a/include/nvtop/interface_common.h b/include/nvtop/interface_common.h index b7d1742..306298a 100644 --- a/include/nvtop/interface_common.h +++ b/include/nvtop/interface_common.h @@ -32,6 +32,7 @@ enum plot_information { plot_fan_speed, plot_gpu_clock_rate, plot_gpu_mem_clock_rate, + plot_effective_load_rate, plot_information_count }; diff --git a/include/nvtop/interface_internal_common.h b/include/nvtop/interface_internal_common.h index 09cc1a7..cf84784 100644 --- a/include/nvtop/interface_internal_common.h +++ b/include/nvtop/interface_internal_common.h @@ -69,6 +69,7 @@ struct device_window { WINDOW *shader_cores; WINDOW *l2_cache_size; WINDOW *exec_engines; + WINDOW *effective_load; bool enc_was_visible; bool dec_was_visible; nvtop_time last_decode_seen; @@ -148,6 +149,7 @@ enum device_field { device_shadercores, device_l2features, device_execengines, + device_effective_load, device_field_count, }; diff --git a/src/extract_gpuinfo.c b/src/extract_gpuinfo.c index 318e6d6..557c52b 100644 --- a/src/extract_gpuinfo.c +++ b/src/extract_gpuinfo.c @@ -97,10 +97,26 @@ bool gpuinfo_populate_static_infos(struct list_head *devices) { return true; } +static void calculate_effective_load(struct gpuinfo_dynamic_info *dynamic_info) { + if (GPUINFO_DYNAMIC_FIELD_VALID(dynamic_info, gpu_util_rate) && + GPUINFO_DYNAMIC_FIELD_VALID(dynamic_info, power_draw) && + GPUINFO_DYNAMIC_FIELD_VALID(dynamic_info, power_draw_max) && dynamic_info->power_draw_max > 0) { + double power_factor = (double)dynamic_info->power_draw / (double)dynamic_info->power_draw_max; + unsigned int effective_load = (unsigned int)(dynamic_info->gpu_util_rate * power_factor); + effective_load = effective_load > 100 ? 100 : effective_load; + SET_GPUINFO_DYNAMIC(dynamic_info, effective_load_rate, effective_load); + } else { + RESET_GPUINFO_DYNAMIC(dynamic_info, effective_load_rate); + } +} + bool gpuinfo_refresh_dynamic_info(struct list_head *devices) { struct gpu_info *device; - list_for_each_entry(device, devices, list) { device->vendor->refresh_dynamic_info(device); } + list_for_each_entry(device, devices, list) { + device->vendor->refresh_dynamic_info(device); + calculate_effective_load(&device->dynamic_info); + } return true; } @@ -157,6 +173,7 @@ bool gpuinfo_fix_dynamic_info_from_process_info(struct list_head *devices) { dynamic_info, gpu_util_rate, (dynamic_info->gpu_util_rate > reportedGpuRate ? dynamic_info->gpu_util_rate : reportedGpuRate)); } + calculate_effective_load(dynamic_info); } return true; } diff --git a/src/interface.c b/src/interface.c index 930a47b..76ea6ee 100644 --- a/src/interface.c +++ b/src/interface.c @@ -45,7 +45,7 @@ static unsigned int sizeof_device_field[device_field_count] = { [device_name] = 11, [device_fan_speed] = 11, [device_temperature] = 10, [device_power] = 15, [device_clock] = 11, [device_mem_clock] = 12, [device_pcie] = 46, [device_shadercores] = 7, - [device_l2features] = 11, [device_execengines] = 11, + [device_l2features] = 11, [device_execengines] = 11, [device_effective_load] = 12, }; static unsigned int sizeof_process_field[process_field_count] = { @@ -94,6 +94,13 @@ static void alloc_device_window(unsigned int start_row, unsigned int start_col, sizeof_device_field[device_temperature] + sizeof_device_field[device_fan_speed]); if (dwin->power_info == NULL) goto alloc_error; + dwin->effective_load = + newwin(1, sizeof_device_field[device_effective_load], start_row + 1, + start_col + spacer * 5 + sizeof_device_field[device_clock] + sizeof_device_field[device_mem_clock] + + sizeof_device_field[device_temperature] + sizeof_device_field[device_fan_speed] + + sizeof_device_field[device_power]); + if (dwin->effective_load == NULL) + goto alloc_error; // Line 3 = GPU used | MEM used | Encoder | Decoder @@ -199,6 +206,7 @@ static void free_device_windows(struct device_window *dwin) { delwin(dwin->gpu_clock_info); delwin(dwin->mem_clock_info); delwin(dwin->power_info); + delwin(dwin->effective_load); delwin(dwin->temperature); delwin(dwin->fan_speed); delwin(dwin->pcie_info); @@ -345,7 +353,7 @@ static unsigned device_length(void) { return max(sizeof_device_field[device_name] + sizeof_device_field[device_pcie] + 1, sizeof_device_field[device_clock] + sizeof_device_field[device_mem_clock] + sizeof_device_field[device_temperature] + sizeof_device_field[device_fan_speed] + - sizeof_device_field[device_power] + 4); + sizeof_device_field[device_power] + sizeof_device_field[device_effective_load] + 5); } static pid_t nvtop_pid; @@ -789,7 +797,16 @@ static void draw_devices(struct list_head *devices, struct nvtop_interface *inte mvwchgat(dev->power_info, 0, 0, 3, 0, cyan_color, NULL); wnoutrefresh(dev->power_info); - // PCIe throughput + // EFFECTIVE LOAD + werase(dev->effective_load); + if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, effective_load_rate)) + mvwprintw(dev->effective_load, 0, 0, "Eff. %3u%%", device->dynamic_info.effective_load_rate); + else + mvwprintw(dev->effective_load, 0, 0, "Eff. N/A%%"); + mvwchgat(dev->effective_load, 0, 0, 4, 0, cyan_color, NULL); + wnoutrefresh(dev->effective_load); + + // PICe throughput werase(dev->pcie_info); if (device->static_info.integrated_graphics) { wcolor_set(dev->pcie_info, cyan_color, NULL); @@ -1690,6 +1707,11 @@ void save_current_data_to_ring(struct list_head *devices, struct nvtop_interface data_val = device->dynamic_info.mem_clock_speed * 100 / device->dynamic_info.mem_clock_speed_max; } break; + case plot_effective_load_rate: + if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, effective_load_rate)) { + data_val = device->dynamic_info.effective_load_rate; + } + break; case plot_information_count: break; } @@ -1756,6 +1778,9 @@ static unsigned populate_plot_data_from_ring_buffer(const struct nvtop_interface case plot_gpu_mem_clock_rate: snprintf(plot_legend[in_processing], PLOT_MAX_LEGEND_SIZE, "GPU%u mem clock%%", dev_id); break; + case plot_effective_load_rate: + snprintf(plot_legend[in_processing], PLOT_MAX_LEGEND_SIZE, "GPU%u eff. load%%", dev_id); + break; case plot_information_count: break; } diff --git a/src/interface_options.c b/src/interface_options.c index e6bc73f..ce9467e 100644 --- a/src/interface_options.c +++ b/src/interface_options.c @@ -192,7 +192,7 @@ static const char device_monitor[] = "Monitor"; static const char device_shown_value[] = "ShownInfo"; static const char *device_draw_vals[plot_information_count + 1] = { "gpuRate", "gpuMemRate", "encodeRate", "decodeRate", "temperature", - "powerDrawRate", "fanSpeed", "gpuClockRate", "gpuMemClockRate", "none"}; + "powerDrawRate", "fanSpeed", "gpuClockRate", "gpuMemClockRate", "effectiveLoadRate", "none"}; static int nvtop_option_ini_handler(void *user, const char *section, const char *name, const char *value) { struct nvtop_option_ini_data *ini_data = (struct nvtop_option_ini_data *)user; diff --git a/src/interface_setup_win.c b/src/interface_setup_win.c index 047809f..ffcc0ef 100644 --- a/src/interface_setup_win.c +++ b/src/interface_setup_win.c @@ -79,7 +79,7 @@ static const char *setup_chart_options_descriptions[setup_chart_options_count] = static const char *setup_chart_gpu_value_descriptions[plot_information_count] = { "GPU utilization rate", "GPU memory utilization rate", "GPU encoder rate", "GPU decoder rate", "GPU temperature", "Power draw rate (current/max)", "Fan speed", "GPU clock rate", - "GPU memory clock rate"}; + "GPU memory clock rate", "Effective load rate"}; // Process List Options