mirror of https://github.com/aristocratos/btop.git
Add GPU info to CPU panel
This commit is contained in:
parent
c352bf2613
commit
22a463976d
25
src/btop.cpp
25
src/btop.cpp
|
@ -499,6 +499,20 @@ namespace Runner {
|
||||||
|
|
||||||
//* Run collection and draw functions for all boxes
|
//* Run collection and draw functions for all boxes
|
||||||
try {
|
try {
|
||||||
|
//? GPU data collection
|
||||||
|
vector<Gpu::gpu_info> gpus;
|
||||||
|
if (
|
||||||
|
v_contains(conf.boxes, "gpu")
|
||||||
|
or Config::getS("cpu_graph_lower") == "default"
|
||||||
|
or Config::getS("cpu_graph_lower").rfind("gpu-", 0) == 0
|
||||||
|
or Config::getS("cpu_graph_upper").rfind("gpu-", 0) == 0
|
||||||
|
or true
|
||||||
|
) {
|
||||||
|
if (Global::debug) debug_timer("gpu", collect_begin);
|
||||||
|
gpus = Gpu::collect(conf.no_update);
|
||||||
|
}
|
||||||
|
auto& gpus_ref = gpus;
|
||||||
|
|
||||||
//? CPU
|
//? CPU
|
||||||
if (v_contains(conf.boxes, "cpu")) {
|
if (v_contains(conf.boxes, "cpu")) {
|
||||||
try {
|
try {
|
||||||
|
@ -518,7 +532,7 @@ namespace Runner {
|
||||||
if (Global::debug) debug_timer("cpu", draw_begin);
|
if (Global::debug) debug_timer("cpu", draw_begin);
|
||||||
|
|
||||||
//? Draw box
|
//? Draw box
|
||||||
if (not pause_output) output += Cpu::draw(cpu, conf.force_redraw, conf.no_update);
|
if (not pause_output) output += Cpu::draw(cpu, gpus_ref, conf.force_redraw, conf.no_update);
|
||||||
|
|
||||||
if (Global::debug) debug_timer("cpu", draw_done);
|
if (Global::debug) debug_timer("cpu", draw_done);
|
||||||
}
|
}
|
||||||
|
@ -527,18 +541,15 @@ namespace Runner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//? GPU
|
//? GPU // TODO detailed panel
|
||||||
if (v_contains(conf.boxes, "gpu")) {
|
if (v_contains(conf.boxes, "gpu")) {
|
||||||
try {
|
try {
|
||||||
if (Global::debug) debug_timer("gpu", collect_begin);
|
|
||||||
|
|
||||||
//? Start collect
|
|
||||||
auto gpus = Gpu::collect(conf.no_update);
|
|
||||||
|
|
||||||
if (Global::debug) debug_timer("gpu", draw_begin);
|
if (Global::debug) debug_timer("gpu", draw_begin);
|
||||||
|
|
||||||
//? Draw box
|
//? Draw box
|
||||||
if (not pause_output and not Gpu::gpu_names.empty()) output += Gpu::draw(gpus, conf.force_redraw, conf.no_update);
|
if (not pause_output and not Gpu::gpu_names.empty())
|
||||||
|
output += Gpu::draw(gpus_ref, conf.force_redraw, conf.no_update);
|
||||||
|
|
||||||
if (Global::debug) debug_timer("gpu", draw_done);
|
if (Global::debug) debug_timer("gpu", draw_done);
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,8 +203,8 @@ namespace Config {
|
||||||
{"graph_symbol_net", "default"},
|
{"graph_symbol_net", "default"},
|
||||||
{"graph_symbol_proc", "default"},
|
{"graph_symbol_proc", "default"},
|
||||||
{"proc_sorting", "cpu lazy"},
|
{"proc_sorting", "cpu lazy"},
|
||||||
{"cpu_graph_upper", "total"},
|
{"cpu_graph_upper", "default"}, // set to "total" in btop_collect.cpp
|
||||||
{"cpu_graph_lower", "total"},
|
{"cpu_graph_lower", "default"}, // set to "total" or "gpu-totals" in btop_collect.cpp
|
||||||
{"cpu_sensor", "Auto"},
|
{"cpu_sensor", "Auto"},
|
||||||
{"selected_battery", "Auto"},
|
{"selected_battery", "Auto"},
|
||||||
{"cpu_core_map", ""},
|
{"cpu_core_map", ""},
|
||||||
|
|
|
@ -495,17 +495,21 @@ namespace Cpu {
|
||||||
int x = 1, y = 1, width = 20, height;
|
int x = 1, y = 1, width = 20, height;
|
||||||
int b_columns, b_column_size;
|
int b_columns, b_column_size;
|
||||||
int b_x, b_y, b_width, b_height;
|
int b_x, b_y, b_width, b_height;
|
||||||
int graph_up_height;
|
|
||||||
long unsigned int lavg_str_len = 0;
|
long unsigned int lavg_str_len = 0;
|
||||||
|
int graph_up_height, graph_low_height;
|
||||||
|
int graph_up_width, graph_low_width;
|
||||||
bool shown = true, redraw = true, mid_line = false;
|
bool shown = true, redraw = true, mid_line = false;
|
||||||
string box;
|
string box;
|
||||||
Draw::Graph graph_upper;
|
vector<Draw::Graph> graphs_upper;
|
||||||
Draw::Graph graph_lower;
|
vector<Draw::Graph> graphs_lower;
|
||||||
Draw::Meter cpu_meter;
|
Draw::Meter cpu_meter;
|
||||||
|
vector<Draw::Meter> gpu_meters;
|
||||||
vector<Draw::Graph> core_graphs;
|
vector<Draw::Graph> core_graphs;
|
||||||
vector<Draw::Graph> temp_graphs;
|
vector<Draw::Graph> temp_graphs;
|
||||||
|
vector<Draw::Graph> gpu_temp_graphs;
|
||||||
|
vector<Draw::Graph> gpu_mem_graphs;
|
||||||
|
|
||||||
string draw(const cpu_info& cpu, bool force_redraw, bool data_same) {
|
string draw(const cpu_info& cpu, const vector<Gpu::gpu_info>& gpus, bool force_redraw, bool data_same) {
|
||||||
if (Runner::stopping) return "";
|
if (Runner::stopping) return "";
|
||||||
if (force_redraw) redraw = true;
|
if (force_redraw) redraw = true;
|
||||||
bool show_temps = (Config::getB("check_temp") and got_sensors);
|
bool show_temps = (Config::getB("check_temp") and got_sensors);
|
||||||
|
@ -531,8 +535,8 @@ namespace Cpu {
|
||||||
//* Redraw elements not needed to be updated every cycle
|
//* Redraw elements not needed to be updated every cycle
|
||||||
if (redraw) {
|
if (redraw) {
|
||||||
mid_line = (not single_graph and graph_up_field != graph_lo_field);
|
mid_line = (not single_graph and graph_up_field != graph_lo_field);
|
||||||
graph_up_height = (single_graph ? height - 2 : ceil((double)(height - 2) / 2) - (mid_line and height % 2 != 0 ? 1 : 0));
|
graph_up_height = (single_graph ? height - 2 : ceil((double)(height - 2) / 2) - (mid_line and height % 2 != 0));
|
||||||
const int graph_low_height = height - 2 - graph_up_height - (mid_line ? 1 : 0);
|
graph_low_height = height - 2 - graph_up_height - mid_line;
|
||||||
const int button_y = cpu_bottom ? y + height - 1 : y;
|
const int button_y = cpu_bottom ? y + height - 1 : y;
|
||||||
out += box;
|
out += box;
|
||||||
|
|
||||||
|
@ -549,17 +553,56 @@ namespace Cpu {
|
||||||
Input::mouse_mappings["+"] = {button_y, x + width - 5, 1, 2};
|
Input::mouse_mappings["+"] = {button_y, x + width - 5, 1, 2};
|
||||||
|
|
||||||
//? Graphs & meters
|
//? Graphs & meters
|
||||||
graph_upper = Draw::Graph{x + width - b_width - 3, graph_up_height, "cpu", cpu.cpu_percent.at(graph_up_field), graph_symbol, false, true};
|
const int graph_default_width = x + width - b_width - 3;
|
||||||
cpu_meter = Draw::Meter{b_width - (show_temps ? 23 - (b_column_size <= 1 and b_columns == 1 ? 6 : 0) : 11), "cpu"};
|
|
||||||
if (not single_graph) {
|
auto init_graphs = [&](vector<Draw::Graph>& graphs, const int graph_height, int& graph_width, const string& graph_field, bool invert) {
|
||||||
graph_lower = Draw::Graph{
|
if (graph_field == "gpu-totals") {
|
||||||
x + width - b_width - 3,
|
graphs.resize(gpus.size());
|
||||||
graph_low_height, "cpu",
|
gpu_temp_graphs.resize(gpus.size());
|
||||||
cpu.cpu_percent.at(graph_lo_field),
|
gpu_mem_graphs.resize(gpus.size());
|
||||||
graph_symbol,
|
gpu_meters.resize(gpus.size());
|
||||||
Config::getB("cpu_invert_lower"), true
|
graph_width = graph_default_width/(int)gpus.size() - (int)gpus.size() + 1 + graph_default_width%gpus.size();
|
||||||
|
for (unsigned long i = 0;;) {
|
||||||
|
auto& gpu = gpus[i]; auto& graph = graphs[i];
|
||||||
|
|
||||||
|
//? GPU graphs/meters
|
||||||
|
gpu_temp_graphs[i] = Draw::Graph{ 5, 1, "temp", gpu.temp, graph_symbol, false, false, gpu.temp_max, -23 };
|
||||||
|
gpu_mem_graphs[i] = Draw::Graph{ 5, 1, "used", gpu.mem_used_percent, graph_symbol };
|
||||||
|
gpu_meters[i] = Draw::Meter{ b_width - 12 - (int)floating_humanizer(gpu.mem_total, true).size() - (show_temps ? 24 : 12) - (int)to_string(i).size(), "cpu" };
|
||||||
|
if (++i < gpus.size())
|
||||||
|
graph = Draw::Graph{graph_width, graph_height, "cpu", gpu.gpu_percent, graph_symbol, invert, true};
|
||||||
|
else {
|
||||||
|
graph = Draw::Graph{
|
||||||
|
graph_width + graph_default_width%graph_width - (int)gpus.size() + 1,
|
||||||
|
graph_height, "cpu", gpu.gpu_percent, graph_symbol, invert, true
|
||||||
};
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else if (graph_field == "gpu-average") {
|
||||||
|
graphs.resize(1);
|
||||||
|
graph_width = graph_default_width;
|
||||||
|
graphs[0] = Draw::Graph{ graph_width, graph_height, "cpu", Gpu::average_gpu_percent, 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) {
|
||||||
|
gpu_temp_graphs[i] = Draw::Graph{ 5, 1, "temp", gpus[i].temp, graph_symbol, false, false, gpus[i].temp_max, -23 };
|
||||||
|
gpu_mem_graphs[i] = Draw::Graph{ 5, 1, "used", gpus[i].mem_used_percent, graph_symbol };
|
||||||
|
gpu_meters[i] = Draw::Meter{ b_width - 12 - (int)floating_humanizer(gpus[i].mem_total, true).size() - (show_temps ? 24 : 12) - (int)to_string(i).size(), "cpu" };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
graphs.resize(1);
|
||||||
|
graph_width = graph_default_width;
|
||||||
|
graphs[0] = Draw::Graph{ graph_width, graph_height, "cpu", cpu.cpu_percent.at(graph_field), graph_symbol, invert, true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
init_graphs(graphs_upper, graph_up_height, graph_up_width, graph_up_field, false);
|
||||||
|
if (not single_graph)
|
||||||
|
init_graphs(graphs_lower, graph_low_height, graph_low_width, graph_lo_field, Config::getB("cpu_invert_lower"));
|
||||||
|
|
||||||
|
cpu_meter = Draw::Meter{b_width - (show_temps ? 23 - (b_column_size <= 1 and b_columns == 1 ? 6 : 0) : 11), "cpu"};
|
||||||
|
|
||||||
if (mid_line) {
|
if (mid_line) {
|
||||||
out += Mv::to(y + graph_up_height + 1, x) + Fx::ub + Theme::c("cpu_box") + Symbols::div_left + Theme::c("div_line")
|
out += Mv::to(y + graph_up_height + 1, x) + Fx::ub + Theme::c("cpu_box") + Symbols::div_left + Theme::c("div_line")
|
||||||
|
@ -627,10 +670,29 @@ namespace Cpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//? Cpu graphs
|
//? Cpu/Gpu graphs
|
||||||
out += Fx::ub + Mv::to(y + 1, x + 1) + graph_upper(cpu.cpu_percent.at(graph_up_field), (data_same or redraw));
|
out += Fx::ub + Mv::to(y + 1, x + 1);
|
||||||
if (not single_graph)
|
auto draw_graphs = [&](vector<Draw::Graph>& graphs, const int graph_height, const int graph_width, const string& graph_field) {
|
||||||
out += Mv::to( y + graph_up_height + 1 + (mid_line ? 1 : 0), x + 1) + graph_lower(cpu.cpu_percent.at(graph_lo_field), (data_same or redraw));
|
if (graph_field == "gpu-totals")
|
||||||
|
for (unsigned long i = 0;;) {
|
||||||
|
out += graphs[i](gpus[i].gpu_percent, (data_same or redraw));
|
||||||
|
if (gpus.size() > 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());
|
||||||
|
}
|
||||||
|
if (++i < 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]((graph_field == "gpu-average" ? Gpu::average_gpu_percent : cpu.cpu_percent.at(graph_field)), (data_same or redraw));
|
||||||
|
};
|
||||||
|
|
||||||
|
draw_graphs(graphs_upper, graph_up_height, graph_up_width, graph_up_field);
|
||||||
|
if (not single_graph) {
|
||||||
|
out += Mv::to(y + graph_up_height + 1 + mid_line, x + 1);
|
||||||
|
draw_graphs(graphs_lower, graph_low_height, graph_low_width, graph_lo_field);
|
||||||
|
}
|
||||||
|
|
||||||
//? Uptime
|
//? Uptime
|
||||||
if (Config::getB("show_uptime")) {
|
if (Config::getB("show_uptime")) {
|
||||||
|
@ -718,7 +780,24 @@ namespace Cpu {
|
||||||
} else {
|
} else {
|
||||||
lavg_str_len = lavg_str.length();
|
lavg_str_len = lavg_str.length();
|
||||||
}
|
}
|
||||||
out += Mv::to(b_y + b_height - 2, b_x + cx + 1) + Theme::c("main_fg") + lavg_str;
|
out += Mv::to(b_y + b_height - 2 - gpus.size(), b_x + cx + 1) + Theme::c("main_fg") + lavg_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Gpu brief info
|
||||||
|
if (graph_lo_field.rfind("gpu-", 0) or graph_up_field.rfind("gpu-", 0))
|
||||||
|
for (unsigned long i = 0; i < gpus.size(); ++i) {
|
||||||
|
out += Mv::to(b_y + b_height - 1 - gpus.size() + i, b_x + 1)
|
||||||
|
+ Theme::c("main_fg") + Fx::b + "GPU " + to_string(i) + ' ' + 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") + '%';
|
||||||
|
out += ' ' + Theme::c("inactive_fg") + graph_bg * 6 + Mv::l(6) + Theme::g("used").at(gpus[i].mem_used_percent.back())
|
||||||
|
+ gpu_mem_graphs[i](gpus[i].mem_used_percent, data_same or redraw) + Theme::c("main_fg")
|
||||||
|
+ rjust(floating_humanizer(gpus[i].mem_used, true), 5) + Theme::c("inactive_fg") + '/' + Theme::c("main_fg") + floating_humanizer(gpus[i].mem_total, true);
|
||||||
|
if (show_temps) {
|
||||||
|
const auto [temp, unit] = celsius_to(gpus[i].temp.back(), temp_scale);
|
||||||
|
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)
|
||||||
|
+ rjust(to_string(temp), 4) + Theme::c("main_fg") + unit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw = false;
|
redraw = false;
|
||||||
|
@ -1752,18 +1831,25 @@ namespace Draw {
|
||||||
//* Calculate and draw cpu box outlines
|
//* Calculate and draw cpu box outlines
|
||||||
if (Cpu::shown) {
|
if (Cpu::shown) {
|
||||||
using namespace Cpu;
|
using namespace Cpu;
|
||||||
bool show_temp = (Config::getB("check_temp") and got_sensors);
|
const bool gpus_shown_in_cpu_panel = (
|
||||||
|
Config::getS("cpu_graph_lower") == "default"
|
||||||
|
or Config::getS("cpu_graph_lower").rfind("gpu-", 0) == 0
|
||||||
|
or Config::getS("cpu_graph_upper").rfind("gpu-", 0) == 0
|
||||||
|
);
|
||||||
|
const int gpus_height_offset = Gpu::gpu_names.size()*gpus_shown_in_cpu_panel;
|
||||||
|
const bool show_temp = (Config::getB("check_temp") and got_sensors);
|
||||||
width = round((double)Term::width * width_p / 100);
|
width = round((double)Term::width * width_p / 100);
|
||||||
if (Gpu::shown and not (Mem::shown or Net::shown or Proc::shown)) {
|
if (Gpu::shown and not (Mem::shown or Net::shown or Proc::shown)) {
|
||||||
height = Term::height/2;
|
height = Term::height/2;
|
||||||
} else {
|
} else {
|
||||||
height = max(8, (int)ceil((double)Term::height * (trim(boxes) == "cpu" ? 100 : height_p/(Gpu::shown+1) + Gpu::shown*5) / 100));
|
height = max(8, (int)ceil((double)Term::height * (trim(boxes) == "cpu" ? 100 : height_p/(Gpu::shown+1) + Gpu::shown*5) / 100));
|
||||||
}
|
}
|
||||||
|
if (height <= Term::height-2) height += gpus_height_offset;
|
||||||
|
|
||||||
x = 1;
|
x = 1;
|
||||||
y = cpu_bottom ? Term::height - height + 1 : 1;
|
y = cpu_bottom ? Term::height - height + 1 : 1;
|
||||||
|
|
||||||
b_columns = max(1, (int)ceil((double)(Shared::coreCount + 1) / (height - 5)));
|
b_columns = max(1, (int)ceil((double)(Shared::coreCount + 1) / (height - gpus_height_offset*(height <= Term::height-2) - 5)));
|
||||||
if (b_columns * (21 + 12 * show_temp) < width - (width / 3)) {
|
if (b_columns * (21 + 12 * show_temp) < width - (width / 3)) {
|
||||||
b_column_size = 2;
|
b_column_size = 2;
|
||||||
b_width = (21 + 12 * show_temp) * b_columns - (b_columns - 1);
|
b_width = (21 + 12 * show_temp) * b_columns - (b_columns - 1);
|
||||||
|
@ -1781,7 +1867,7 @@ namespace Draw {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b_column_size == 0) b_width = (8 + 6 * show_temp) * b_columns + 1;
|
if (b_column_size == 0) b_width = (8 + 6 * show_temp) * b_columns + 1;
|
||||||
b_height = min(height - 2, (int)ceil((double)Shared::coreCount / b_columns) + 4);
|
b_height = min(height - 2, (int)ceil((double)Shared::coreCount / b_columns) + 4 + (int)gpus_height_offset - gpus_shown_in_cpu_panel);
|
||||||
|
|
||||||
b_x = x + width - b_width - 1;
|
b_x = x + width - b_width - 1;
|
||||||
b_y = y + ceil((double)(height - 2) / 2) - ceil((double)b_height / 2) + 1;
|
b_y = y + ceil((double)(height - 2) / 2) - ceil((double)b_height / 2) + 1;
|
||||||
|
|
|
@ -86,6 +86,61 @@ namespace Shared {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gpu {
|
||||||
|
extern string box;
|
||||||
|
extern int x, y, width, height, min_width, min_height;
|
||||||
|
extern bool shown, redraw;
|
||||||
|
extern vector<string> gpu_names;
|
||||||
|
extern deque<long long> average_gpu_percent;
|
||||||
|
|
||||||
|
const array mem_names { "used"s, "free"s };
|
||||||
|
|
||||||
|
//* Container for process information // TODO
|
||||||
|
/*struct proc_info {
|
||||||
|
unsigned int pid;
|
||||||
|
unsigned long long mem;
|
||||||
|
};*/
|
||||||
|
|
||||||
|
//* Per-device container for GPU info
|
||||||
|
struct gpu_info {
|
||||||
|
deque<long long> gpu_percent = {0};
|
||||||
|
unsigned int gpu_clock_speed = 0; // MHz
|
||||||
|
|
||||||
|
deque<long long> pwr_percent = {0};
|
||||||
|
long long pwr_usage = 0; // mW
|
||||||
|
long long pwr_max_usage = 255000;
|
||||||
|
long long pwr_state = 32;
|
||||||
|
|
||||||
|
deque<long long> temp = {0};
|
||||||
|
long long temp_max = 110;
|
||||||
|
|
||||||
|
long long mem_total = 0;
|
||||||
|
long long mem_used = 0;
|
||||||
|
deque<long long> mem_used_percent = {0};
|
||||||
|
deque<long long> mem_utilization_percent = {0}; // TODO: properly handle GPUs that can't report some stats
|
||||||
|
long long mem_clock_speed = 0; // MHz
|
||||||
|
|
||||||
|
long long pcie_tx = 0; // KB/s
|
||||||
|
long long pcie_rx = 0;
|
||||||
|
|
||||||
|
// vector<proc_info> graphics_processes = {}; // TODO
|
||||||
|
// vector<proc_info> compute_processes = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Nvml {
|
||||||
|
extern bool shutdown();
|
||||||
|
}
|
||||||
|
namespace Rsmi {
|
||||||
|
extern bool shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Collect gpu stats and temperatures
|
||||||
|
auto collect(bool no_update = false) -> vector<gpu_info>&;
|
||||||
|
|
||||||
|
//* Draw contents of gpu box using <gpus> as source
|
||||||
|
string draw(const vector<gpu_info>& gpus, bool force_redraw, bool data_same);
|
||||||
|
}
|
||||||
|
|
||||||
namespace Cpu {
|
namespace Cpu {
|
||||||
extern string box;
|
extern string box;
|
||||||
extern int x, y, width, height, min_width, min_height;
|
extern int x, y, width, height, min_width, min_height;
|
||||||
|
@ -119,7 +174,7 @@ namespace Cpu {
|
||||||
auto collect(bool no_update = false) -> cpu_info&;
|
auto collect(bool no_update = false) -> cpu_info&;
|
||||||
|
|
||||||
//* Draw contents of cpu box using <cpu> as source
|
//* Draw contents of cpu box using <cpu> as source
|
||||||
string draw(const cpu_info& cpu, bool force_redraw = false, bool data_same = false);
|
string draw(const cpu_info& cpu, const vector<Gpu::gpu_info>& gpu, bool force_redraw = false, bool data_same = false);
|
||||||
|
|
||||||
//* Parse /proc/cpu info for mapping of core ids
|
//* Parse /proc/cpu info for mapping of core ids
|
||||||
auto get_core_mapping() -> unordered_flat_map<int, int>;
|
auto get_core_mapping() -> unordered_flat_map<int, int>;
|
||||||
|
@ -313,57 +368,3 @@ namespace Proc {
|
||||||
int cur_depth, bool collapsed, const string& filter,
|
int cur_depth, bool collapsed, const string& filter,
|
||||||
bool found = false, bool no_update = false, bool should_filter = false);
|
bool found = false, bool no_update = false, bool should_filter = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Gpu {
|
|
||||||
extern string box;
|
|
||||||
extern int x, y, width, height, min_width, min_height;
|
|
||||||
extern bool shown, redraw;
|
|
||||||
extern vector<string> gpu_names;
|
|
||||||
|
|
||||||
const array mem_names { "used"s, "free"s };
|
|
||||||
|
|
||||||
//* Container for process information // TODO
|
|
||||||
/*struct proc_info {
|
|
||||||
unsigned int pid;
|
|
||||||
unsigned long long mem;
|
|
||||||
};*/
|
|
||||||
|
|
||||||
//* Per-device container for GPU info
|
|
||||||
struct gpu_info {
|
|
||||||
deque<long long> gpu_percent = {0};
|
|
||||||
unsigned int gpu_clock_speed = 0; // MHz
|
|
||||||
|
|
||||||
deque<long long> pwr_percent = {0};
|
|
||||||
long long pwr_usage = 0; // mW
|
|
||||||
long long pwr_max_usage = 255000;
|
|
||||||
long long pwr_state = 32;
|
|
||||||
|
|
||||||
deque<long long> temp = {0};
|
|
||||||
long long temp_max = 110;
|
|
||||||
|
|
||||||
long long mem_total = 0;
|
|
||||||
long long mem_used = 0;
|
|
||||||
deque<long long> mem_used_percent = {0};
|
|
||||||
deque<long long> mem_utilization_percent = {0}; // TODO: properly handle GPUs that can't report some stats
|
|
||||||
long long mem_clock_speed = 0; // MHz
|
|
||||||
|
|
||||||
long long pcie_tx = 0; // KB/s
|
|
||||||
long long pcie_rx = 0;
|
|
||||||
|
|
||||||
// vector<proc_info> graphics_processes = {}; // TODO
|
|
||||||
// vector<proc_info> compute_processes = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Nvml {
|
|
||||||
extern bool shutdown();
|
|
||||||
}
|
|
||||||
namespace Rsmi {
|
|
||||||
extern bool shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
//* Collect gpu stats and temperatures
|
|
||||||
auto collect(bool no_update = false) -> vector<gpu_info>&;
|
|
||||||
|
|
||||||
//* Draw contents of gpu box using <gpus> as source
|
|
||||||
string draw(const vector<gpu_info>& gpus, bool force_redraw, bool data_same);
|
|
||||||
}
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ namespace Cpu {
|
||||||
namespace Gpu {
|
namespace Gpu {
|
||||||
vector<gpu_info> gpus;
|
vector<gpu_info> gpus;
|
||||||
vector<string> gpu_names;
|
vector<string> gpu_names;
|
||||||
|
deque<long long> average_gpu_percent = {};
|
||||||
|
|
||||||
//? NVIDIA data collection
|
//? NVIDIA data collection
|
||||||
namespace Nvml {
|
namespace Nvml {
|
||||||
|
@ -172,13 +173,24 @@ namespace Shared {
|
||||||
}
|
}
|
||||||
Cpu::core_mapping = Cpu::get_core_mapping();
|
Cpu::core_mapping = Cpu::get_core_mapping();
|
||||||
|
|
||||||
|
//? Init for namespace Gpu
|
||||||
|
Gpu::Nvml::init();
|
||||||
|
Gpu::Rsmi::init();
|
||||||
|
if (not Gpu::gpu_names.empty()) {
|
||||||
|
Cpu::available_fields.push_back("gpu-totals");
|
||||||
|
Cpu::available_fields.push_back("gpu-average");
|
||||||
|
if (Config::strings.at("cpu_graph_lower") == "default")
|
||||||
|
Config::strings.at("cpu_graph_lower") = "gpu-totals";
|
||||||
|
}
|
||||||
|
|
||||||
//? Init for namespace Mem
|
//? Init for namespace Mem
|
||||||
Mem::old_uptime = system_uptime();
|
Mem::old_uptime = system_uptime();
|
||||||
Mem::collect();
|
Mem::collect();
|
||||||
|
|
||||||
//? Init for namespace Gpu
|
if (Config::strings.at("cpu_graph_upper") == "default")
|
||||||
Gpu::Nvml::init();
|
Config::strings.at("cpu_graph_upper") = "total";
|
||||||
Gpu::Rsmi::init();
|
if (Config::strings.at("cpu_graph_lower") == "default")
|
||||||
|
Config::strings.at("cpu_graph_lower") = "total";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -870,7 +882,13 @@ namespace Gpu {
|
||||||
result = nvmlDeviceGetName(devices[i], name, NVML_DEVICE_NAME_BUFFER_SIZE);
|
result = nvmlDeviceGetName(devices[i], name, NVML_DEVICE_NAME_BUFFER_SIZE);
|
||||||
if (result != NVML_SUCCESS)
|
if (result != NVML_SUCCESS)
|
||||||
Logger::error(std::string("NVML: Failed to get device name: ") + nvmlErrorString(result));
|
Logger::error(std::string("NVML: Failed to get device name: ") + nvmlErrorString(result));
|
||||||
else gpu_names[i] = string(name);
|
else {
|
||||||
|
gpu_names[i] = string(name);
|
||||||
|
for (const auto& brand : {"NVIDIA", "Nvidia", "AMD", "Amd", "Intel", "(R)", "(TM)"}) {
|
||||||
|
gpu_names[i] = s_replace(gpu_names[i], brand, "");
|
||||||
|
}
|
||||||
|
gpu_names[i] = trim(gpu_names[i]);
|
||||||
|
}
|
||||||
|
|
||||||
//? Power usage
|
//? Power usage
|
||||||
unsigned int max_power;
|
unsigned int max_power;
|
||||||
|
@ -1150,8 +1168,13 @@ namespace Gpu {
|
||||||
Nvml::collect(gpus.data()); // raw pointer to vector data, size == Nvml::device_count
|
Nvml::collect(gpus.data()); // raw pointer to vector data, size == Nvml::device_count
|
||||||
Rsmi::collect(gpus.data() + Nvml::device_count); // size = Rsmi::device_count
|
Rsmi::collect(gpus.data() + Nvml::device_count); // size = Rsmi::device_count
|
||||||
|
|
||||||
//* Trim vectors if there are more values than needed for graphs
|
//* Calculate average usage
|
||||||
|
long long avg = 0;
|
||||||
for (auto& gpu : gpus) {
|
for (auto& gpu : gpus) {
|
||||||
|
avg += gpu.gpu_percent.back();
|
||||||
|
|
||||||
|
//* Trim vectors if there are more values than needed for graphs
|
||||||
|
if (width != 0) {
|
||||||
//? GPU & memory utilization
|
//? GPU & memory utilization
|
||||||
while (cmp_greater(gpu.gpu_percent.size(), width * 2)) gpu.gpu_percent.pop_front();
|
while (cmp_greater(gpu.gpu_percent.size(), width * 2)) gpu.gpu_percent.pop_front();
|
||||||
while (cmp_greater(gpu.mem_utilization_percent.size(), width)) gpu.mem_utilization_percent.pop_front();
|
while (cmp_greater(gpu.mem_utilization_percent.size(), width)) gpu.mem_utilization_percent.pop_front();
|
||||||
|
@ -1162,6 +1185,11 @@ namespace Gpu {
|
||||||
//? Memory usage
|
//? Memory usage
|
||||||
while (cmp_greater(gpu.mem_used_percent.size(), width/2)) gpu.mem_used_percent.pop_front();
|
while (cmp_greater(gpu.mem_used_percent.size(), width/2)) gpu.mem_used_percent.pop_front();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
average_gpu_percent.push_back(avg / gpus.size());
|
||||||
|
|
||||||
|
if (width != 0)
|
||||||
|
while (cmp_greater(average_gpu_percent.size(), width * 2)) average_gpu_percent.pop_front();
|
||||||
|
|
||||||
return gpus;
|
return gpus;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue