Handle GPUs which cannot report certain stats in GPU panel

This commit is contained in:
romner 2023-05-21 20:34:47 +02:00
parent 414d7eb94c
commit 8c96bd51e9
3 changed files with 112 additions and 74 deletions

View file

@ -808,7 +808,7 @@ namespace Cpu {
for (unsigned long i = 0; i < gpus.size(); ++i) {
if (not v_contains(Gpu::shown_panels, i)) {
out += Mv::to(b_y + b_height - 1 - gpus.size() + ++shown_panels_count - (Gpu::shown == 0), b_x + 1)
+ Theme::c("main_fg") + Fx::b + "GPU " + (gpus.size() > 1 ? rjust(to_string(i) + ' ', 1 + gpus.size() > 9) : "");
+ Theme::c("main_fg") + Fx::b + "GPU " + (gpus.size() > 1 ? ((gpus.size() > 9 and i <= 9 ? " " : "") + to_string(i) + ' ') : "");
if (gpus[i].supported_functions.gpu_utilization)
out += gpu_meters[i](gpus[i].gpu_percent.back())
+ Theme::g("cpu").at(gpus[i].gpu_percent.back()) + rjust(to_string(gpus[i].gpu_percent.back()), 4) + Theme::c("main_fg") + '%';
@ -842,8 +842,8 @@ namespace Gpu {
int width_p = 100, height_p = 32;
int min_width = 41, min_height = 9;
int width = 41, height;
vector<int> x_vec = {}, y_vec = {};
int b_width, b_height;
vector<int> x_vec = {}, y_vec = {}, b_height_vec = {};
int b_width;
vector<int> b_x_vec = {}, b_y_vec = {};
vector<bool> redraw = {}, mid_line = {};
int shown = 0;
@ -873,7 +873,7 @@ namespace Gpu {
auto& pwr_meter = pwr_meter_vec[index];
if (force_redraw) redraw[index] = true;
bool show_temps = (Config::getB("check_temp"));
bool show_temps = gpu.supported_functions.temp_info and (Config::getB("check_temp"));
auto tty_mode = Config::getB("tty_mode");
auto& temp_scale = Config::getS("temp_scale");
auto& graph_symbol = (tty_mode ? "tty" : Config::getS("graph_symbol_cpu")); // TODO graph_symbol_gpu
@ -888,93 +888,120 @@ namespace Gpu {
const int graph_low_height = height - 2 - graph_up_height - (mid_line[index] ? 1 : 0);
out += box[index];
graph_upper = Draw::Graph{x + width - b_width - 3, graph_up_height, "cpu", gpu.gpu_percent, graph_symbol, false, true}; // TODO cpu -> gpu
if (not single_graph) {
graph_lower = Draw::Graph{
x + width - b_width - 3,
graph_low_height, "cpu",
gpu.gpu_percent,
graph_symbol,
Config::getB("cpu_invert_lower"), true
};
}
gpu_meter = Draw::Meter{b_width - (show_temps ? 24 : 11), "cpu"};
temp_graph = Draw::Graph{6, 1, "temp", gpu.temp, graph_symbol, false, false, gpu.temp_max, -23};
pwr_meter = Draw::Meter{b_width - 24, "cached"};
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
mem_used_graph = Draw::Graph{b_width/2 - 2, 4, "used", gpu.mem_used_percent, graph_symbol};
if (gpu.supported_functions.gpu_utilization) {
graph_upper = Draw::Graph{x + width - b_width - 3, graph_up_height, "cpu", gpu.gpu_percent, graph_symbol, false, true}; // TODO cpu -> gpu
if (not single_graph) {
graph_lower = Draw::Graph{
x + width - b_width - 3,
graph_low_height, "cpu",
gpu.gpu_percent,
graph_symbol,
Config::getB("cpu_invert_lower"), true
};
}
gpu_meter = Draw::Meter{b_width - (show_temps ? 24 : 11), "cpu"};
}
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"};
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)
mem_used_graph = Draw::Graph{b_width/2 - 2, 2 + 2*(gpu.supported_functions.mem_utilization), "used", gpu.mem_used_percent, graph_symbol};
}
//* General GPU info
//? Gpu graph, clock speed & meter
out += Fx::ub + Mv::to(y + 1, x + 1) + graph_upper(gpu.gpu_percent, (data_same or redraw[index]));
if (not single_graph)
out += Mv::to(y + graph_up_height + 1 + mid_line[index], x + 1) + graph_lower(gpu.gpu_percent, (data_same or redraw[index]));
//? Gpu graph, meter & clock speed
if (gpu.supported_functions.gpu_utilization) {
out += Fx::ub + Mv::to(y + 1, x + 1) + graph_upper(gpu.gpu_percent, (data_same or redraw[index]));
if (not single_graph)
out += Mv::to(y + graph_up_height + 1 + mid_line[index], x + 1) + graph_lower(gpu.gpu_percent, (data_same or redraw[index]));
if (Config::getB("show_cpu_freq")) { // TODO show_gpu_freq
out += Mv::to(b_y + 1, b_x + 1) + Theme::c("main_fg") + Fx::b + "GPU " + gpu_meter(gpu.gpu_percent.back())
+ Theme::g("cpu").at(gpu.gpu_percent.back()) + rjust(to_string(gpu.gpu_percent.back()), 4) + Theme::c("main_fg") + '%';
//? Temperature graph, I assume the device supports utilization if it supports temperature
if (show_temps) {
const auto [temp, unit] = celsius_to(gpu.temp.back(), temp_scale);
out += ' ' + Theme::c("inactive_fg") + graph_bg * 6 + Mv::l(6) + Theme::g("temp").at(clamp(gpu.temp.back() * 100 / gpu.temp_max, 0ll, 100ll))
+ temp_graph(gpu.temp, data_same or redraw[index]);
out += rjust(to_string(temp), 4) + Theme::c("main_fg") + unit;
}
out += Theme::c("div_line") + Symbols::v_line;
}
if (gpu.supported_functions.gpu_clock and Config::getB("show_cpu_freq")) { // TODO show_gpu_freq
string clock_speed_string = to_string(gpu.gpu_clock_speed);
out += Mv::to(b_y, b_x + b_width - 12) + Theme::c("div_line") + Symbols::h_line*(5-clock_speed_string.size())
+ Symbols::title_left + Fx::b + Theme::c("title") + clock_speed_string + " Mhz" + Fx::ub + Theme::c("div_line") + Symbols::title_right;
}
out += Mv::to(b_y + 1, b_x + 1) + Theme::c("main_fg") + Fx::b + "GPU " + gpu_meter(gpu.gpu_percent.back())
+ Theme::g("cpu").at(gpu.gpu_percent.back()) + rjust(to_string(gpu.gpu_percent.back()), 4) + Theme::c("main_fg") + '%';
//? Temperature graph
if (show_temps) {
const auto [temp, unit] = celsius_to(gpu.temp.back(), temp_scale);
out += ' ' + Theme::c("inactive_fg") + graph_bg * 6 + Mv::l(6) + Theme::g("temp").at(clamp(gpu.temp.back() * 100 / gpu.temp_max, 0ll, 100ll))
+ temp_graph(gpu.temp, data_same or redraw[index]);
out += rjust(to_string(temp), 4) + Theme::c("main_fg") + unit;
}
out += Theme::c("div_line") + Symbols::v_line;
//? Power usage meter, power state
out += Mv::to(b_y + 2, b_x + 1) + Theme::c("main_fg") + Fx::b + "PWR " + pwr_meter(gpu.pwr_percent.back())
+ Theme::g("cached").at(gpu.pwr_percent.back()) + rjust(to_string(gpu.pwr_usage/1000), 4) + Theme::c("main_fg") + 'W';
if (gpu.pwr_state != 32) // NVML_PSTATE_UNKNOWN; unsupported or non-nvidia card
out += std::string(" P-state: ") + (gpu.pwr_state > 9 ? "" : " ") + 'P' + Theme::g("cached").at(gpu.pwr_state) + to_string(gpu.pwr_state);
//? Memory section header & clock speed
string used_memory_string = floating_humanizer(gpu.mem_used);
out += Mv::to(b_y + 3, b_x) + Theme::c("div_line") + Symbols::div_left + Symbols::h_line + Symbols::title_left + Fx::b + Theme::c("title") + "vram"
+ Theme::c("div_line") + Fx::ub + Symbols::title_right + Symbols::h_line*(b_width/2-8) + Symbols::div_up + Symbols::h_line
+ Theme::c("title") + "Used:" + Theme::c("div_line") + Symbols::h_line*(b_width/2+b_width%2-9-used_memory_string.size()) + Theme::c("title") + used_memory_string + Theme::c("div_line") + Symbols::h_line + Symbols::div_right;
if (Config::getB("show_cpu_freq")) { // TODO show_gpu_freq
string clock_speed_string = to_string(gpu.mem_clock_speed);
out += Mv::to(b_y + 3, b_x + b_width/2 - 11) + Theme::c("div_line") + Symbols::h_line*(5-clock_speed_string.size())
+ Symbols::title_left + Fx::b + Theme::c("title") + clock_speed_string + " Mhz" + Fx::ub + Theme::c("div_line") + Symbols::title_right;
if (gpu.supported_functions.pwr_usage) {
out += Mv::to(b_y + 2, b_x + 1) + Theme::c("main_fg") + Fx::b + "PWR " + pwr_meter(gpu.pwr_percent.back())
+ Theme::g("cached").at(gpu.pwr_percent.back()) + rjust(to_string(gpu.pwr_usage/1000), 4) + Theme::c("main_fg") + 'W';
if (gpu.supported_functions.pwr_state and gpu.pwr_state != 32) // NVML_PSTATE_UNKNOWN; unsupported or non-nvidia card
out += std::string(" P-state: ") + (gpu.pwr_state > 9 ? "" : " ") + 'P' + Theme::g("cached").at(gpu.pwr_state) + to_string(gpu.pwr_state);
}
//? Memory usage borders
out += Mv::to(b_y + 5, b_x) + Theme::c("div_line") + Symbols::div_left+Symbols::h_line + Theme::c("title") + "Utilization:" + Theme::c("div_line") + Symbols::h_line*(b_width/2-14)
+ Symbols::div_right + Mv::u(1)+Mv::l(1) + Symbols::v_line + Mv::l(1)+Mv::d(2) + (Symbols::v_line + Mv::l(1)+Mv::d(1))*2;
if (gpu.supported_functions.mem_total or gpu.supported_functions.mem_used) {
out += Mv::to(b_y + 3, b_x);
if (gpu.supported_functions.mem_total and gpu.supported_functions.mem_used) {
string used_memory_string = floating_humanizer(gpu.mem_used);
//? Total memory usage
out += Mv::to(b_y + 4, b_x + 2) + Theme::c("main_fg") + Fx::b + "Total:" + rjust(floating_humanizer(gpu.mem_total), b_width/2-9) + Fx::ub;
auto offset = (gpu.supported_functions.mem_total or gpu.supported_functions.mem_used)
* (1 + 2*(gpu.supported_functions.mem_total and gpu.supported_functions.mem_used) + 2*gpu.supported_functions.mem_utilization);
//? Memory usage graphs & percentage
out += Mv::to(b_y+6, b_x+1) + Theme::c("inactive_fg") + mem_util_graph(gpu.mem_utilization_percent, (data_same or redraw[index]))
+ Mv::u(3) + Mv::r(1) + mem_used_graph(gpu.mem_used_percent, (data_same or redraw[index]));
out += Mv::to(b_y+6, b_x+1) + rjust(to_string(gpu.mem_utilization_percent.back()), 3) + '%' + Mv::u(2) + Mv::r(b_width/2-3) + rjust(to_string(gpu.mem_used_percent.back()), 3) + '%';
//? Used graph, memory section header, total vram
out += Theme::c("div_line") + Symbols::div_left + Symbols::h_line + Symbols::title_left + Fx::b + Theme::c("title") + "vram" + Theme::c("div_line") + Fx::ub + Symbols::title_right
+ Symbols::h_line*(b_width/2-8) + Symbols::div_up + Mv::d(offset)+Mv::l(1) + Symbols::div_down + Mv::l(1)+Mv::u(1) + (Symbols::v_line + Mv::l(1)+Mv::u(1))*(offset-1) + Symbols::div_up
+ Symbols::h_line + Theme::c("title") + "Used:" + Theme::c("div_line")
+ Symbols::h_line*(b_width/2+b_width%2-9-used_memory_string.size()) + Theme::c("title") + used_memory_string + Theme::c("div_line") + Symbols::h_line + Symbols::div_right
+ Mv::d(1) + Mv::l(b_width/2-1) + mem_used_graph(gpu.mem_used_percent, (data_same or redraw[index]))
+ Mv::l(b_width-3) + Mv::u(1+2*gpu.supported_functions.mem_utilization) + Theme::c("main_fg") + Fx::b + "Total:" + rjust(floating_humanizer(gpu.mem_total), b_width/2-9) + Fx::ub
+ Mv::r(3) + rjust(to_string(gpu.mem_used_percent.back()), 3) + '%';
//? Memory utilization
if (gpu.supported_functions.mem_utilization)
out += Mv::l(b_width/2+6) + Mv::d(1) + Theme::c("div_line") + Symbols::div_left+Symbols::h_line + Theme::c("title") + "Utilization:" + Theme::c("div_line") + Symbols::h_line*(b_width/2-14) + Symbols::div_right
+ Mv::l(b_width/2) + Mv::d(1) + mem_util_graph(gpu.mem_utilization_percent, (data_same or redraw[index]))
+ Mv::l(b_width/2-1) + Mv::u(1) + rjust(to_string(gpu.mem_utilization_percent.back()), 3) + '%';
//? Memory clock speed
if (gpu.supported_functions.mem_clock and Config::getB("show_cpu_freq")) { // TODO show_gpu_freq
string clock_speed_string = to_string(gpu.mem_clock_speed);
out += Mv::to(b_y + 3, b_x + b_width/2 - 11) + Theme::c("div_line") + Symbols::h_line*(5-clock_speed_string.size())
+ Symbols::title_left + Fx::b + Theme::c("title") + clock_speed_string + " Mhz" + Fx::ub + Theme::c("div_line") + Symbols::title_right;
}
} else {
out += Theme::c("main_fg") + Mv::r(1);
bool clock_shown = gpu.supported_functions.mem_clock and Config::getB("show_cpu_freq"); // TODO show_gpu_freq
if (gpu.supported_functions.mem_total)
out += "VRAM total:" + rjust(floating_humanizer(gpu.mem_total), b_width/(1 + clock_shown)-14);
else out += "VRAM usage:" + rjust(floating_humanizer(gpu.mem_used), b_width/(1 + clock_shown)-14);
if (clock_shown)
out += " VRAM clock:" + rjust(to_string(gpu.mem_clock_speed) + " Mhz", b_width/2-13);
}
}
//? Processes section header
//out += Mv::to(b_y+8, b_x) + Theme::c("div_line") + Symbols::div_left + Symbols::h_line + Symbols::title_left + Theme::c("main_fg") + Fx::b + "gpu-proc" + Fx::ub + Theme::c("div_line")
// + Symbols::title_right + Symbols::h_line*(b_width/2-12) + Symbols::div_down + Symbols::h_line*(b_width/2-2) + Symbols::div_right;
//? PCIe link throughput
string tx_string = floating_humanizer(gpu.pcie_tx, 0, 1, 0, 1);
string rx_string = floating_humanizer(gpu.pcie_rx, 0, 1, 0, 1);
out += Mv::to(b_y + b_height - 1, b_x+2) + Theme::c("div_line")
+ Symbols::title_left_down + Theme::c("title") + Fx::b + "TX:" + Fx::ub + Theme::c("div_line") + Symbols::title_right_down + Symbols::h_line*(b_width/2-9-tx_string.size())
+ Symbols::title_left_down + Theme::c("title") + Fx::b + tx_string + Fx::ub + Theme::c("div_line") + Symbols::title_right_down + Symbols::div_down
+ Symbols::title_left_down + Theme::c("title") + Fx::b + "RX:" + Fx::ub + Theme::c("div_line") + Symbols::title_right_down + Symbols::h_line*(b_width/2+b_width%2-9-rx_string.size())
+ Symbols::title_left_down + Theme::c("title") + Fx::b + rx_string + Fx::ub + Theme::c("div_line") + Symbols::title_right_down + Symbols::round_right_down;
if (gpu.supported_functions.pcie_txrx) {
string tx_string = floating_humanizer(gpu.pcie_tx, 0, 1, 0, 1);
string rx_string = floating_humanizer(gpu.pcie_rx, 0, 1, 0, 1);
out += Mv::to(b_y + b_height_vec[index] - 1, b_x+2) + Theme::c("div_line")
+ Symbols::title_left_down + Theme::c("title") + Fx::b + "TX:" + Fx::ub + Theme::c("div_line") + Symbols::title_right_down + Symbols::h_line*(b_width/2-9-tx_string.size())
+ Symbols::title_left_down + Theme::c("title") + Fx::b + tx_string + Fx::ub + Theme::c("div_line") + Symbols::title_right_down + (gpu.supported_functions.mem_total and gpu.supported_functions.mem_used ? Symbols::div_down : Symbols::h_line)
+ Symbols::title_left_down + Theme::c("title") + Fx::b + "RX:" + Fx::ub + Theme::c("div_line") + Symbols::title_right_down + Symbols::h_line*(b_width/2+b_width%2-9-rx_string.size())
+ Symbols::title_left_down + Theme::c("title") + Fx::b + rx_string + Fx::ub + Theme::c("div_line") + Symbols::title_right_down + Symbols::round_right_down;
}
redraw[index] = false;
return out + Fx::reset;
@ -1935,6 +1962,7 @@ namespace Draw {
using namespace Gpu;
x_vec.resize(shown); y_vec.resize(shown);
b_x_vec.resize(shown); b_y_vec.resize(shown);
b_height_vec.resize(shown);
box.resize(shown);
graph_upper_vec.resize(shown); graph_lower_vec.resize(shown);
temp_graph_vec.resize(shown);
@ -1952,14 +1980,14 @@ namespace Draw {
x_vec[i] = 1; y_vec[i] = 1 + i*height + (not Config::getB("cpu_bottom"))*Cpu::shown*Cpu::height;
box[i] = createBox(x_vec[i], y_vec[i], width, height, Theme::c("cpu_box"), true, std::string("gpu") + (char)(shown_panels[i]+'0'), "", (shown_panels[i]+5)%10); // TODO gpu_box
b_height = 9;
b_width = clamp(width/2, min_width, b_height*6);
b_height_vec[i] = 2 + gpu_b_height_offsets[shown_panels[i]];
b_width = clamp(width/2, min_width, 64);
//? Main statistics box
b_x_vec[i] = x_vec[i] + width - b_width - 1;
b_y_vec[i] = y_vec[i] + ceil((double)(height - 2) / 2) - ceil((double)(b_height) / 2) + 1;
b_y_vec[i] = y_vec[i] + ceil((double)(height - 2) / 2) - ceil((double)(b_height_vec[i]) / 2) + 1;
box[i] += createBox(b_x_vec[i], b_y_vec[i], b_width, b_height, "", false, gpu_names[shown_panels[i]].substr(0, b_width-5));
box[i] += createBox(b_x_vec[i], b_y_vec[i], b_width, b_height_vec[i], "", false, gpu_names[shown_panels[i]].substr(0, b_width-5));
}
}

View file

@ -94,6 +94,7 @@ namespace Gpu {
extern int shown;
extern vector<char> shown_panels;
extern vector<string> gpu_names;
extern vector<int> gpu_b_height_offsets;
extern deque<long long> average_gpu_percent;
const array mem_names { "used"s, "free"s };

View file

@ -98,6 +98,7 @@ namespace Cpu {
namespace Gpu {
vector<gpu_info> gpus;
vector<string> gpu_names;
vector<int> gpu_b_height_offsets;
deque<long long> average_gpu_percent = {};
//? NVIDIA data collection
@ -189,6 +190,14 @@ namespace Shared {
Cpu::available_fields.push_back("gpu-average");
if (Config::strings.at("cpu_graph_lower") == "default")
Config::strings.at("cpu_graph_lower") = "gpu-totals";
using namespace Gpu;
gpu_b_height_offsets.resize(gpus.size());
for (ulong i = 0; i < gpu_b_height_offsets.size(); ++i)
gpu_b_height_offsets[i] = gpus[i].supported_functions.gpu_utilization
+ gpus[i].supported_functions.pwr_usage
+ (gpus[i].supported_functions.mem_total or gpus[i].supported_functions.mem_used)
* (1 + 2*(gpus[i].supported_functions.mem_total and gpus[i].supported_functions.mem_used) + 2*gpus[i].supported_functions.mem_utilization);
}
//? Init for namespace Mem
@ -1121,7 +1130,7 @@ namespace Gpu {
int64_t temp_max;
result = rsmi_dev_temp_metric_get(i, RSMI_TEMP_TYPE_EDGE, RSMI_TEMP_MAX, &temp_max);
if (result != RSMI_STATUS_SUCCESS)
Logger::warning("ROCm SMI: Failed to get maximum GPU temperature, defaulting to 110");
Logger::warning("ROCm SMI: Failed to get maximum GPU temperature, defaulting to 110°C");
else gpus[offset].temp_max = (long long)temp_max;
}
initialized = true;