Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intel GPU support #903

Merged
merged 9 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/cmake-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- uses: actions/checkout@v4

- name: Install build tools
run: apk add --no-cache --update clang cmake lld ninja lowdown
run: apk add --no-cache --update clang cmake lld ninja lowdown linux-headers

- name: Configure
run: CXX=clang++ LDFLAGS=-fuse-ld=lld cmake -B build -G Ninja -DBTOP_STATIC=ON
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/continuous-build-gpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- uses: actions/checkout@v4

- name: Install build tools
run: apk add --no-cache --update gcc g++ make
run: apk add --no-cache --update gcc g++ make linux-headers

- name: Compile
run: make CXX=g++ GPU_SUPPORT=true
Expand Down
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ endif()
project("btop"
DESCRIPTION "A monitor of resources"
HOMEPAGE_URL "https://github.com/aristocratos/btop"
LANGUAGES CXX
LANGUAGES CXX C
)

include(CheckCXXCompilerFlag)
Expand Down Expand Up @@ -70,6 +70,14 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
target_sources(btop PRIVATE src/netbsd/btop_collect.cpp)
elseif(LINUX)
target_sources(btop PRIVATE src/linux/btop_collect.cpp)
if(BTOP_GPU)
target_sources(btop PRIVATE
src/linux/intel_gpu_top/intel_gpu_top.c
src/linux/intel_gpu_top/igt_perf.c
src/linux/intel_gpu_top/intel_device_info.c
src/linux/intel_gpu_top/intel_name_lookup_shim.c
)
endif()
else()
message(FATAL_ERROR "${CMAKE_SYSTEM_NAME} is not supported")
endif()
Expand Down
32 changes: 27 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]')
ifeq ($(PLATFORM_LC)$(ARCH),linuxx86_64)
ifneq ($(STATIC),true)
GPU_SUPPORT := true
INTEL_GPU_SUPPORT := true
endif
endif
ifneq ($(GPU_SUPPORT),true)
Expand Down Expand Up @@ -208,13 +209,22 @@ endif

SOURCES := $(sort $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT)))

SOURCES += $(sort $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT)))

#? Setup percentage progress
SOURCE_COUNT := $(words $(SOURCES))
SOURCES += $(sort $(shell find $(SRCDIR)/$(PLATFORM_DIR) -maxdepth 1 -type f -name *.$(SRCEXT)))

OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))

ifeq ($(GPU_SUPPORT)$(INTEL_GPU_SUPPORT),truetrue)
IGT_OBJECTS := $(BUILDDIR)/igt_perf.c.o $(BUILDDIR)/intel_device_info.c.o $(BUILDDIR)/intel_name_lookup_shim.c.o $(BUILDDIR)/intel_gpu_top.c.o
OBJECTS += $(IGT_OBJECTS)
SHOW_CC_INFO = false
CC_VERSION := $(shell $(CC) -dumpfullversion -dumpversion || echo 0)
else
SHOW_CC_INFO = true
endif

#? Setup percentage progress
SOURCE_COUNT := $(words $(OBJECTS))

ifeq ($(shell find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o >/dev/null 2>&1; echo $$?),0)
ifneq ($(wildcard $(BUILDDIR)/.*),)
SKIPPED_SOURCES := $(foreach fname,$(SOURCES),$(shell find $(BUILDDIR) -type f -newer $(fname) -name *.o | grep "$(basename $(notdir $(fname))).o" 2>/dev/null))
Expand Down Expand Up @@ -248,7 +258,8 @@ info:
@printf "\033[1;96mARCH \033[1;93m?| \033[0m$(ARCH)\n"
@printf "\033[1;95mGPU_SUPPORT \033[1;94m:| \033[0m$(GPU_SUPPORT)\n"
@printf "\033[1;93mCXX \033[1;93m?| \033[0m$(CXX) \033[1;93m(\033[97m$(CXX_VERSION)\033[93m)\n"
@printf "\033[1;94mTHREADS \033[1;94m:| \033[0m$(THREADS)\n"
@$(SHOW_CC_INFO) || printf "\033[1;93mCC \033[1;93m?| \033[0m$(CC) \033[1;93m(\033[97m$(CC_VERSION)\033[93m)\n"
@printf "\033[1;94mTHREADS \033[1;94m:| \033[0m$(THREADS)\n" gcc -dumpfullversion -dumpversion
@printf "\033[1;92mREQFLAGS \033[1;91m!| \033[0m$(REQFLAGS)\n"
@printf "\033[1;91mWARNFLAGS \033[1;94m:| \033[0m$(WARNFLAGS)\n"
@printf "\033[1;94mOPTFLAGS \033[1;94m:| \033[0m$(OPTFLAGS)\n"
Expand Down Expand Up @@ -409,5 +420,16 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) | rocm_smi directories config.h
@$(CXX) $(CXXFLAGS) $(INC) -MMD -c -o $@ $< || exit 1
@printf "\033[1;92m$$($(PROGRESS))$(P)\033[10D\033[5C-> \033[1;37m$@ \033[100D\033[38C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$($(DATE_CMD) +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n"

#? Compile intel_gpu_top C sources for Intel GPU support
.ONESHELL:
$(BUILDDIR)/%.c.o: $(SRCDIR)/$(PLATFORM_DIR)/intel_gpu_top/%.c | directories
@sleep 0.3 2>/dev/null || true
@TSTAMP=$$(date +%s 2>/dev/null || echo "0")
@$(QUIET) || printf "\033[1;97mCompiling $<\033[0m\n"
@$(VERBOSE) || printf "$(CC) $(INC) -c -o $@ $<\n"
@$(CC) $(INC) -w -c -o $@ $< || exit 1
@printf "\033[1;92m$$($(PROGRESS))$(P)\033[10D\033[5C-> \033[1;37m$@ \033[100D\033[38C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$($(DATE_CMD) +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n"


#? Non-File Targets
.PHONY: all config.h msg help pre
135 changes: 134 additions & 1 deletion src/linux/btop_collect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ tab-size = 4
#include "../btop_config.hpp"
#include "../btop_tools.hpp"

#if defined(GPU_SUPPORT)
#define class class_
extern "C" {
#include "./intel_gpu_top/intel_gpu_top.h"
}
#undef class
#endif

using std::clamp;
using std::cmp_greater;
using std::cmp_less;
Expand Down Expand Up @@ -210,6 +218,19 @@ namespace Gpu {
template <bool is_init> bool collect(gpu_info* gpus_slice);
uint32_t device_count = 0;
}


//? Intel data collection
namespace Intel {
const char* device = "i915";
struct engines *engines = nullptr;

bool initialized = false;
bool init();
bool shutdown();
template <bool is_init> bool collect(gpu_info* gpus_slice);
uint32_t device_count = 0;
}
#endif
}

Expand Down Expand Up @@ -276,6 +297,7 @@ namespace Shared {
#ifdef GPU_SUPPORT
Gpu::Nvml::init();
Gpu::Rsmi::init();
Gpu::Intel::init();
if (not Gpu::gpu_names.empty()) {
for (auto const& [key, _] : Gpu::gpus[0].gpu_percent)
Cpu::available_fields.push_back(key);
Expand Down Expand Up @@ -1570,7 +1592,117 @@ namespace Gpu {
}
}

// TODO: Intel
namespace Intel {
bool init() {
if (initialized) return false;

char *gpu_path = find_intel_gpu_dir();
if (!gpu_path) {
Logger::debug("Failed to find Intel GPU sysfs path, Intel GPUs will not be detected");
return false;
}

char *gpu_device_id = get_intel_device_id(gpu_path);
if (!gpu_device_id) {
Logger::debug("Failed to find Intel GPU device ID, Intel GPUs will not be detected");
return false;
}

char *gpu_device_name = get_intel_device_name(gpu_device_id);
if (!gpu_device_name) {
Logger::warning("Failed to find Intel GPU device name in internal database");
}

free(gpu_device_id);

engines = discover_engines(device);
if (!engines) {
Logger::debug("Failed to find Intel GPU engines, Intel GPUs will not be detected");
return false;
}

int ret = pmu_init(engines);
if (ret) {
Logger::warning("Intel GPU: Failed to initialize PMU");
return false;
}

pmu_sample(engines);

device_count = 1;

gpus.resize(gpus.size() + device_count);
gpu_names.resize(gpus.size() + device_count);

if (gpu_device_name) {
gpu_names[Nvml::device_count + Rsmi::device_count] = string(gpu_device_name);
} else {
gpu_names[Nvml::device_count + Rsmi::device_count] = "Intel GPU";
}

free(gpu_device_name);

initialized = true;
Intel::collect<1>(gpus.data() + Nvml::device_count + Rsmi::device_count);

return true;
}

bool shutdown() {
if (!initialized) return false;
if (engines) {
free_engines(engines);
engines = nullptr;
}
initialized = false;
return true;
}

template <bool is_init> bool collect(gpu_info* gpus_slice) {
if (!initialized) return false;

if constexpr(is_init) {
gpus_slice->supported_functions = {
.gpu_utilization = true,
.mem_utilization = false,
.gpu_clock = true,
.mem_clock = false,
.pwr_usage = true,
.pwr_state = false,
.temp_info = false,
.mem_total = false,
.mem_used = false,
.pcie_txrx = false
};
}

pmu_sample(engines);
double t = (double)(engines->ts.cur - engines->ts.prev) / 1e9;

double max_util = 0;
for (unsigned int i = 0; i < engines->num_engines; i++) {
struct engine *engine = &(&engines->engine)[i];
double util = pmu_calc(&engine->busy.val, 1e9, t, 100);
if (util > max_util) {
max_util = util;
}
}
gpus_slice->gpu_percent.at("gpu-totals").push_back((long long)round(max_util));

double pwr = pmu_calc(&engines->r_gpu.val, 1, t, engines->r_gpu.scale); // in Watts
gpus_slice->pwr_usage = (long long)round(pwr * 1000);
if (gpus_slice->pwr_usage > 0) {
gpus_slice->gpu_percent.at("gpu-pwr-totals").push_back(100);
} else {
gpus_slice->gpu_percent.at("gpu-pwr-totals").push_back(0);
}

double freq = pmu_calc(&engines->freq_act.val, 1, t, 1); // in MHz
gpus_slice->gpu_clock_speed = (unsigned int)round(freq);

return true;
}
}

//? Collect data from GPU-specific libraries
auto collect(bool no_update) -> vector<gpu_info>& {
Expand All @@ -1581,6 +1713,7 @@ namespace Gpu {
//* Collect data
Nvml::collect<0>(gpus.data()); // raw pointer to vector data, size == Nvml::device_count
Rsmi::collect<0>(gpus.data() + Nvml::device_count); // size = Rsmi::device_count
Intel::collect<0>(gpus.data() + Nvml::device_count + Rsmi::device_count); // size = Intel::device_count

//* Calculate average usage
long long avg = 0;
Expand Down
Loading
Loading