Skip to content

Commit

Permalink
GPU fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
aristocratos committed Sep 21, 2024
1 parent 24fc97c commit 35857f8
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 118 deletions.
5 changes: 3 additions & 2 deletions src/btop_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ namespace Config {
{"proc_aggregate", false},
#ifdef GPU_SUPPORT
{"nvml_measure_pcie_speeds", true},
{"gpu_mirror_graph", true},
{"rsmi_measure_pcie_speeds", true},
{"gpu_mirror_graph", true}
#endif
};
std::unordered_map<std::string_view, bool> boolsTmp;
Expand All @@ -320,7 +321,7 @@ namespace Config {
{"selected_depth", 0},
{"proc_start", 0},
{"proc_selected", 0},
{"proc_last_selected", 0},
{"proc_last_selected", 0}
};
std::unordered_map<std::string_view, int> intsTmp;

Expand Down
222 changes: 109 additions & 113 deletions src/btop_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,8 @@ namespace Cpu {
#ifdef GPU_SUPPORT
const auto& show_gpu_info = Config::getS("show_gpu_info");
const bool gpu_always = show_gpu_info == "On";
bool show_gpu = (gpus.size() > 0 and (gpu_always or (show_gpu_info == "Auto" and Gpu::shown == 0)));
const bool gpu_auto = show_gpu_info == "Auto";
const bool show_gpu = (gpus.size() > 0 and (gpu_always or (gpu_auto and Gpu::shown < Gpu::count)));
#else
(void)gpus;
#endif
Expand Down Expand Up @@ -576,6 +577,7 @@ namespace Cpu {
graph_up_height = (single_graph ? height - 2 : ceil((double)(height - 2) / 2) - (mid_line and height % 2 != 0));
graph_low_height = height - 2 - graph_up_height - mid_line;
const int button_y = cpu_bottom ? y + height - 1 : y;
lavg_str_len = 0;
out += box;

//? Buttons on title
Expand All @@ -601,72 +603,38 @@ namespace Cpu {
gpu_temp_graphs.resize(gpus.size());
gpu_mem_graphs.resize(gpus.size());
gpu_meters.resize(gpus.size());
graph_width = graph_default_width/(int)gpus.size() - (int)gpus.size() + 1 + graph_default_width%gpus.size();
for (unsigned long i = 0;;) {
const int gpu_draw_count = gpu_always ? Gpu::count : Gpu::count - Gpu::shown;
graph_width = gpu_draw_count <= 0 ? graph_default_width : graph_default_width/gpu_draw_count - gpu_draw_count + 1 + graph_default_width%gpu_draw_count;
for (size_t i = 0; i < gpus.size(); i++) {
if (gpu_auto and v_contains(Gpu::shown_panels, i))
continue;
auto& gpu = gpus[i]; auto& graph = graphs[i];

//? GPU graphs/meters
if (gpu.supported_functions.temp_info)
gpu_temp_graphs[i] = Draw::Graph{ 5, 1, "temp", gpu.temp, graph_symbol, false, false, gpu.temp_max, -23 };
if (gpu.supported_functions.mem_used and gpu.supported_functions.mem_total)
gpu_mem_graphs[i] = Draw::Graph{ 5, 1, "used", safeVal(gpu.gpu_percent, "gpu-vram-totals"s), graph_symbol };
//? GPU graphs
if (gpu.supported_functions.gpu_utilization) {
gpu_meter_width = b_width - 12 - (int)floating_humanizer(gpu.mem_total, true).size() - (show_temps ? 24 : 12) - (int)to_string(i).size() + (gpus.size() == 1)*2 - (gpus.size() > 9 and i <= 9);
gpu_meters[i] = Draw::Meter{gpu_meter_width, "cpu" };
}

bool utilization_support = gpu.supported_functions.gpu_utilization;
if (++i < gpus.size()) {
if (utilization_support)
if (i + 1 < gpus.size()) {
graph = Draw::Graph{graph_width, graph_height, "cpu", safeVal(gpu.gpu_percent, graph_field), graph_symbol, invert, true};
} else {
if (utilization_support)
}
else {
graph = Draw::Graph{
graph_width + graph_default_width%graph_width - (int)gpus.size() + 1,
graph_height, "cpu", safeVal(gpu.gpu_percent, graph_field), graph_symbol, invert, true
};
break;
}
}
}
} else {
graphs.resize(1);
graph_width = graph_default_width;
graphs[0] = Draw::Graph{ graph_width, graph_height, "cpu", safeVal(Gpu::shared_gpu_percent, graph_field), graph_symbol, invert, true };
gpu_temp_graphs.resize(gpus.size());
gpu_mem_graphs.resize(gpus.size());
gpu_meters.resize(gpus.size());
for (unsigned long i = 0; i < gpus.size(); ++i) {
if (gpus[i].supported_functions.temp_info)
gpu_temp_graphs[i] = Draw::Graph{ 5, 1, "temp", gpus[i].temp, graph_symbol, false, false, gpus[i].temp_max, -23 };
if (gpus[i].supported_functions.mem_used and gpus[i].supported_functions.mem_total)
gpu_mem_graphs[i] = Draw::Graph{ 5, 1, "used", safeVal(gpus[i].gpu_percent, "gpu-vram-totals"s), graph_symbol };
if (gpus[i].supported_functions.gpu_utilization) {
gpu_meter_width = b_width - 12 - (int)floating_humanizer(gpus[i].mem_total, true).size() - (show_temps ? 24 : 12) - (int)to_string(i).size() + (gpus.size() == 1)*2 - (gpus.size() > 9 and i <= 9);
gpu_meters[i] = Draw::Meter{gpu_meter_width, "cpu" };
}
}
}
} else {
}
else {
#endif
graphs.resize(1);
graph_width = graph_default_width;
graphs[0] = Draw::Graph{ graph_width, graph_height, "cpu", safeVal(cpu.cpu_percent, graph_field), graph_symbol, invert, true };
#ifdef GPU_SUPPORT
if (std::cmp_less(Gpu::shown, gpus.size())) {
gpu_temp_graphs.resize(gpus.size());
gpu_mem_graphs.resize(gpus.size());
gpu_meters.resize(gpus.size());
for (unsigned long i = 0; i < gpus.size(); ++i) {
if (gpus[i].supported_functions.temp_info)
gpu_temp_graphs[i] = Draw::Graph{ 5, 1, "temp", gpus[i].temp, graph_symbol, false, false, gpus[i].temp_max, -23 };
if (gpus[i].supported_functions.mem_used and gpus[i].supported_functions.mem_total)
gpu_mem_graphs[i] = Draw::Graph{ 5, 1, "used", safeVal(gpus[i].gpu_percent, "gpu-vram-totals"s), graph_symbol };
if (gpus[i].supported_functions.gpu_utilization) {
gpu_meter_width = b_width - 12 - (int)floating_humanizer(gpus[i].mem_total, true).size() - (show_temps ? 24 : 12) - (int)to_string(i).size() + (gpus.size() == 1)*2 - (gpus.size() > 9 and i <= 9);
gpu_meters[i] = Draw::Meter{gpu_meter_width, "cpu" };
}
}
}
}
#endif
};
Expand All @@ -675,6 +643,37 @@ namespace Cpu {
if (not single_graph)
init_graphs(graphs_lower, graph_low_height, graph_low_width, graph_lo_field, Config::getB("cpu_invert_lower"));

#ifdef GPU_SUPPORT
if (show_gpu and b_columns > 1) {
gpu_temp_graphs.resize(gpus.size());
gpu_mem_graphs.resize(gpus.size());
gpu_meters.resize(gpus.size());

for (size_t i = 0; i < gpus.size(); i++) {
if (gpu_auto and v_contains(Gpu::shown_panels, i))
continue;
auto& gpu = gpus[i];

//? GPU graphs/meters
auto width_left = b_width - 10 - (gpus.size() > 9 ? 2 : gpus.size() > 1 ? 1 : 0);
if (gpu.supported_functions.temp_info and show_temps) {
gpu_temp_graphs[i] = Draw::Graph{ 5, 1, "temp", gpu.temp, graph_symbol, false, false, gpu.temp_max, -23 };
width_left -= 11;
}
if (gpu.supported_functions.mem_used and gpu.supported_functions.mem_total and b_columns > 1) {
gpu_mem_graphs[i] = Draw::Graph{ 5, 1, "used", safeVal(gpu.gpu_percent, "gpu-vram-totals"s), graph_symbol };
width_left -= 5;
}
width_left -= (gpu.supported_functions.mem_used ? 5 : 0);
width_left -= (gpu.supported_functions.mem_total ? 6 : 0);
width_left -= (gpu.supported_functions.pwr_usage ? 5 : 0);
if (gpu.supported_functions.gpu_utilization) {
gpu_meters[i] = Draw::Meter{width_left, "cpu" };
}
}
}
#endif

cpu_meter = Draw::Meter{b_width - (show_temps ? 23 - (b_column_size <= 1 and b_columns == 1 ? 6 : 0) : 11), "cpu"};

if (mid_line) {
Expand Down Expand Up @@ -752,17 +751,18 @@ namespace Cpu {
#ifdef GPU_SUPPORT
if (graph_field.starts_with("gpu"))
if (graph_field.find("totals") != string::npos)
for (unsigned long i = 0;;) {
for (size_t i = 0; i < gpus.size(); i++) {
if (gpu_auto and v_contains(Gpu::shown_panels, i))
continue;
out += graphs[i](safeVal(gpus[i].gpu_percent, graph_field), (data_same or redraw));
if (gpus.size() > 1) {
if (Gpu::count - Gpu::shown > 1) {
auto i_str = to_string(i);
out += Mv::l(graph_width-1) + Mv::u(graph_height/2) + (graph_width > 5 ? "GPU " : "") + i_str
+ Mv::d(graph_height/2) + Mv::r(graph_width - 1 - (graph_width > 5)*4 - i_str.size());
out += Mv::l(graph_width-1) + Mv::u(graph_height/2) + (graph_width > 5 ? "GPU" : "") + i_str
+ Mv::d(graph_height/2) + Mv::r(graph_width - 1 - (graph_width > 5)*3 - i_str.size());
}

if (++i < graphs.size())
if (i + 1 < graphs.size())
out += Theme::c("div_line") + (Symbols::v_line + Mv::l(1) + Mv::u(1))*graph_height + Mv::r(1) + Mv::d(1);
else break;
}
else
out += graphs[0](safeVal(Gpu::shared_gpu_percent, graph_field), (data_same or redraw));
Expand Down Expand Up @@ -845,23 +845,15 @@ namespace Cpu {
if (cy < b_height - 1 and cc <= b_columns) {
string lavg_pre;
int sep = 1;
if (b_column_size == 2 and show_temps) { lavg_pre = "Load AVG:"; sep = 3; }
if (b_column_size == 2 and show_temps) { lavg_pre = "Load AVG: "; sep = 3; }
else if (b_column_size == 2 or (b_column_size == 1 and show_temps)) { lavg_pre = "LAV:"; }
else if (b_column_size == 1 or (b_column_size == 0 and show_temps)) { lavg_pre = "L"; }
else if (b_column_size == 1 or (b_column_size == 0 and show_temps)) { lavg_pre = "L "; }
string lavg;
for (const auto& val : cpu.load_avg) {
lavg += string(sep, ' ') + (lavg_pre.size() < 3 ? to_string((int)round(val)) : to_string(val).substr(0, 4));
}

string lavg_str = lavg_pre + lavg;
// if previous load average string is longer than current
// then right pad the current string with spaces until
// the current string is the same length as the previous
// otherwise set the lavg_str_len.
//
// When a shorter string gets written, the remaining characters
// from the previous string get left behind. This "erases" the
// leftover characters from the previous string.
if (lavg_str_len > lavg_str.length()) {
lavg_str += string(lavg_str_len - lavg_str.length(), ' ');
} else {
Expand All @@ -879,37 +871,45 @@ namespace Cpu {
//? Gpu brief info
if (show_gpu) {
for (unsigned long i = 0; i < gpus.size(); ++i) {
if (gpu_always or not v_contains(Gpu::shown_panels, i)) {
out += Mv::to(b_y + ++cy, b_x + 1) + Theme::c("main_fg") + Fx::b + "GPU";
if (show_temps and gpus[i].supported_functions.temp_info and b_width < 34) {
const auto [temp, unit] = celsius_to(gpus[i].temp.back(), temp_scale);
if (temp < 100) out += " ";
}
if (gpus.size() > 1) out += rjust(to_string(i), 1 + (gpus.size() > 9));
if (gpus[i].supported_functions.gpu_utilization) {
string meter = gpu_meters[i](safeVal(gpus[i].gpu_percent, "gpu-totals"s).back());
out += (meter.size() > 1 ? " " : "") + meter
+ Theme::g("cpu").at(clamp(safeVal(gpus[i].gpu_percent, "gpu-totals"s).back(), 0ll, 100ll)) + rjust(to_string(safeVal(gpus[i].gpu_percent, "gpu-totals"s).back()), 4) + Theme::c("main_fg") + '%';
} else out += Mv::r(gpu_meter_width);

if (gpus[i].supported_functions.mem_used) {
out += ' ' + Theme::c("inactive_fg") + graph_bg * 6 + Mv::l(6) + Theme::g("used").at(safeVal(gpus[i].gpu_percent, "gpu-vram-totals"s).back())
+ gpu_mem_graphs[i](safeVal(gpus[i].gpu_percent, "gpu-vram-totals"s), data_same or redraw) + Theme::c("main_fg")
+ rjust(floating_humanizer(gpus[i].mem_used, true), 5);
if (gpus[i].supported_functions.mem_total)
out += Theme::c("inactive_fg") + '/' + Theme::c("main_fg") + floating_humanizer(gpus[i].mem_total, true);
else out += Mv::r(5);
} else out += Mv::r(17);
if (show_temps and gpus[i].supported_functions.temp_info) {
const auto [temp, unit] = celsius_to(gpus[i].temp.back(), temp_scale);
if (b_width > 38)
out += ' ' + Theme::c("inactive_fg") + graph_bg * 6 + Mv::l(6) + Theme::g("temp").at(clamp(gpus[i].temp.back() * 100 / gpus[i].temp_max, 0ll, 100ll))
+ gpu_temp_graphs[i](gpus[i].temp, data_same or redraw);
else out += Theme::g("temp").at(clamp(gpus[i].temp.back() * 100 / gpus[i].temp_max, 0ll, 100ll));
out += rjust(to_string(temp), 3 + (b_width >= 34 or temp > 99)) + Theme::c("main_fg") + unit;
if (gpu_auto and v_contains(Gpu::shown_panels, i))
continue;
out += Mv::to(b_y + ++cy, b_x + 1) + Theme::c("main_fg") + Fx::b + "GPU";
if (gpus.size() > 1) out += rjust(to_string(i), 1 + (gpus.size() > 9));
if (gpus[i].supported_functions.gpu_utilization) {
out += ' ';
if (b_columns > 1) {
out += gpu_meters[i](safeVal(gpus[i].gpu_percent, "gpu-totals"s).back())
+ Theme::g("cpu").at(clamp(safeVal(gpus[i].gpu_percent, "gpu-totals"s).back(), 0ll, 100ll));
}
out += rjust(to_string(safeVal(gpus[i].gpu_percent, "gpu-totals"s).back()), 3) + Theme::c("main_fg") + '%';
if (b_columns == 1)
out += ' ';
}
if (gpus[i].supported_functions.mem_used and gpus[i].supported_functions.mem_total and b_columns > 1) {
out += ' ' + Theme::c("inactive_fg") + graph_bg * 5 + Mv::l(5) + Theme::g("used").at(safeVal(gpus[i].gpu_percent, "gpu-vram-totals"s).back())
+ gpu_mem_graphs[i](safeVal(gpus[i].gpu_percent, "gpu-vram-totals"s), data_same or redraw);
}
if (cy < b_height - 1) break;
if (gpus[i].supported_functions.mem_used) {
out += Theme::c("main_fg")
+ rjust(floating_humanizer(gpus[i].mem_used, true), 5);
}
if (gpus[i].supported_functions.mem_total) {
out += Theme::c("inactive_fg") + '/' + Theme::c("main_fg") + ljust(floating_humanizer(gpus[i].mem_total, true), 4);
}
if (show_temps and gpus[i].supported_functions.temp_info) {
const auto [temp, unit] = celsius_to(gpus[i].temp.back(), temp_scale);
out += ' ';
if (b_columns > 1)
out += Theme::c("inactive_fg") + graph_bg * 5 + Mv::l(5) + Theme::g("temp").at(clamp(gpus[i].temp.back() * 100 / gpus[i].temp_max, 0ll, 100ll))
+ gpu_temp_graphs[i](gpus[i].temp, data_same or redraw);
else out += Theme::g("temp").at(clamp(gpus[i].temp.back() * 100 / gpus[i].temp_max, 0ll, 100ll));
out += rjust(to_string(temp), 3) + Theme::c("main_fg") + unit;
}
if (gpus[i].supported_functions.pwr_usage) {
out += ' ' + Theme::g("cached").at(clamp(safeVal(gpus[i].gpu_percent, "gpu-pwr-totals"s).back(), 0ll, 100ll)) + rjust(to_string(gpus[i].pwr_usage/1000), 3) + Theme::c("main_fg") + 'W';
}

if (cy > b_height - 1) break;
}
}
#endif
Expand All @@ -930,7 +930,8 @@ namespace Gpu {
vector<int> b_x_vec = {}, b_y_vec = {};
vector<bool> redraw = {};
int shown = 0;
vector<char> shown_panels = {};
int count = 0;
vector<int> shown_panels = {};
int graph_up_height;
vector<Draw::Graph> graph_upper_vec = {}, graph_lower_vec = {};
vector<Draw::Graph> temp_graph_vec = {};
Expand Down Expand Up @@ -987,7 +988,7 @@ namespace Gpu {
if (gpu.supported_functions.temp_info)
temp_graph = Draw::Graph{6, 1, "temp", gpu.temp, graph_symbol, false, false, gpu.temp_max, -23};
if (gpu.supported_functions.pwr_usage)
pwr_meter = Draw::Meter{b_width - 24, "cached"};
pwr_meter = Draw::Meter{b_width - (gpu.supported_functions.pwr_state and gpu.pwr_state != 32 ? 24 : 11), "cached"};
if (gpu.supported_functions.mem_utilization)
mem_util_graph = Draw::Graph{b_width/2 - 1, 2, "free", gpu.mem_utilization_percent, graph_symbol, 0, 0, 100, 4}; // offset so the graph isn't empty at 0-5% utilization
if (gpu.supported_functions.mem_used and gpu.supported_functions.mem_total)
Expand Down Expand Up @@ -1990,19 +1991,16 @@ namespace Draw {
Gpu::box.clear();
Gpu::width = 0;
Gpu::shown_panels.clear();
if (not Gpu::gpu_names.empty()) {
if (Gpu::count > 0) {
std::istringstream iss(boxes, std::istringstream::in);
string current;
while (iss >> current)
if ( current == "gpu0"
or current == "gpu1"
or current == "gpu2"
or current == "gpu3"
or current == "gpu4"
or current == "gpu5"
) Gpu::shown_panels.push_back(current.back()-'0');
while (iss >> current) {
if (current.starts_with("gpu"))
Gpu::shown_panels.push_back(current.back()-'0');
}
}
Gpu::shown = Gpu::shown_panels.size();

#endif
Mem::shown = s_contains(boxes, "mem");
Net::shown = s_contains(boxes, "net");
Expand All @@ -2012,31 +2010,28 @@ namespace Draw {
if (Cpu::shown) {
using namespace Cpu;
#ifdef GPU_SUPPORT
const bool show_gpu_on = Config::getS("show_gpu_info") == "On";
const bool gpus_shown_in_cpu_panel = Gpu::gpu_names.size() > 0 and (
show_gpu_on or (Config::getS("show_gpu_info") == "Auto" and Gpu::shown == 0)
);
const int gpus_height_offset = (Gpu::gpu_names.size() - Gpu::shown)*gpus_shown_in_cpu_panel;
int gpus_extra_height = gpus_shown_in_cpu_panel ? Gpu::gpu_names.size() - (show_gpu_on ? 0 : Gpu::shown) : 0;
int gpus_extra_height =
Config::getS("show_gpu_info") == "On" ? Gpu::count
: Config::getS("show_gpu_info") == "Auto" ? Gpu::count - Gpu::shown
: 0;
#endif
const bool show_temp = (Config::getB("check_temp") and got_sensors);
width = round((double)Term::width * width_p / 100);
#ifdef GPU_SUPPORT
if (Gpu::shown != 0 and not (Mem::shown or Net::shown or Proc::shown)) {
height = Term::height - Gpu::min_height*Gpu::shown - gpus_height_offset;
height = Term::height - Gpu::min_height*Gpu::shown - gpus_extra_height;
} else {
height = max(8, (int)ceil((double)Term::height * (trim(boxes) == "cpu" ? 100 : height_p/(Gpu::shown+1) + (Gpu::shown != 0)*5) / 100));
}
if (height <= Term::height-gpus_height_offset) height += gpus_height_offset;
if (height - gpus_extra_height < 7) gpus_extra_height = height - 7;
if (height <= Term::height-gpus_extra_height) height += gpus_extra_height;
#else
height = max(8, (int)ceil((double)Term::height * (trim(boxes) == "cpu" ? 100 : height_p) / 100));
#endif
x = 1;
y = cpu_bottom ? Term::height - height + 1 : 1;

#ifdef GPU_SUPPORT
b_columns = max(1, (int)ceil((double)(Shared::coreCount + 1) / (height - gpus_extra_height - 5)));
b_columns = max(2, (int)ceil((double)(Shared::coreCount + 1) / (height - gpus_extra_height - 5)));
#else
b_columns = max(1, (int)ceil((double)(Shared::coreCount + 1) / (height - 5)));
#endif
Expand All @@ -2058,6 +2053,7 @@ namespace Draw {

if (b_column_size == 0) b_width = (8 + 6 * show_temp) * b_columns + 1;
#ifdef GPU_SUPPORT
//gpus_extra_height = max(0, gpus_extra_height - 1);
b_height = min(height - 2, (int)ceil((double)Shared::coreCount / b_columns) + 4 + gpus_extra_height);
#else
b_height = min(height - 2, (int)ceil((double)Shared::coreCount / b_columns) + 4);
Expand Down
6 changes: 6 additions & 0 deletions src/btop_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,12 @@ namespace Menu {
"May impact performance on certain cards.",
"",
"True or False."},
{"rsmi_measure_pcie_speeds",
"Measure PCIe throughput on AMD cards.",
"",
"May impact performance on certain cards.",
"",
"True or False."},
{"graph_symbol_gpu",
"Graph symbol to use for graphs in gpu box.",
"",
Expand Down
2 changes: 1 addition & 1 deletion src/btop_shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ namespace Gpu {
{"gpu-vram-total", {}},
{"gpu-pwr-total", {}},
};
long long gpu_pwr_total_max;
long long gpu_pwr_total_max = 0;
}
#endif

Expand Down
Loading

0 comments on commit 35857f8

Please sign in to comment.