mirror of
https://github.com/Syllo/nvtop.git
synced 2026-08-02 08:25:53 -04:00
Merge branch 'master' into master
This commit is contained in:
@@ -92,7 +92,7 @@ endif()
|
||||
|
||||
option(NVIDIA_SUPPORT "Build support for NVIDIA GPUs through libnvml" ${NVIDIA_SUPPORT_DEFAULT})
|
||||
option(AMDGPU_SUPPORT "Build support for AMD GPUs through amdgpu driver" ${AMDGPU_SUPPORT_DEFAULT})
|
||||
option(INTEL_SUPPORT "Build support for Intel GPUs through i915 driver" ${INTEL_SUPPORT_DEFAULT})
|
||||
option(INTEL_SUPPORT "Build support for Intel GPUs through i915 or xe driver" ${INTEL_SUPPORT_DEFAULT})
|
||||
option(MSM_SUPPORT "Build support for Adreno GPUs through msm driver" ${MSM_SUPPORT_DEFAULT})
|
||||
option(APPLE_SUPPORT "Build support for Apple GPUs through Metal" ${APPLE_SUPPORT_DEFAULT})
|
||||
option(PANFROST_SUPPORT "Build support for Mali GPUs through panfrost driver" ${PANFROST_SUPPORT_DEFAULT})
|
||||
|
||||
@@ -17,7 +17,7 @@ RUN apt-get update && \
|
||||
# Get a recent-enough CMake
|
||||
RUN python3 -m venv /.venv && \
|
||||
. /.venv/bin/activate && \
|
||||
pip install --upgrade pip \
|
||||
pip install --upgrade pip && \
|
||||
pip install cmake
|
||||
|
||||
COPY . /nvtop
|
||||
|
||||
@@ -9,7 +9,7 @@ accelerators. It can handle multiple GPUs and print information about them in a
|
||||
htop-familiar way.
|
||||
|
||||
Currently supported vendors are AMD (Linux amdgpu driver), Apple (limited M1 &
|
||||
M2 support), Huawei (Ascend), Intel (Linux i915 driver), NVIDIA (Linux
|
||||
M2 support), Huawei (Ascend), Intel (Linux i915/Xe drivers), NVIDIA (Linux
|
||||
proprietary divers), Qualcomm Adreno (Linux MSM driver), Broadcom VideoCore (Linux v3d driver).
|
||||
|
||||
Because a picture is worth a thousand words:
|
||||
@@ -40,6 +40,7 @@ Table of Contents
|
||||
- [Arch Linux](#arch-linux)
|
||||
- [AppImage](#appimage)
|
||||
- [Snap](#snap)
|
||||
- [Conda-forge](#conda-forge)
|
||||
- [Docker](#docker)
|
||||
- [NVTOP Build](#nvtop-build)
|
||||
- [Troubleshoot](#troubleshoot)
|
||||
@@ -89,7 +90,7 @@ use a recent-enough kernel for your GPU.
|
||||
|
||||
### Intel
|
||||
|
||||
NVTOP supports Intel GPUs using the `i915` linux driver.
|
||||
NVTOP supports Intel GPUs using the `i915` or `xe` linux driver.
|
||||
|
||||
Intel introduced the fdinfo interface in kernel 5.19 ([browse kernel
|
||||
source](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/gpu/drm/i915/i915_drm_client.c?h=linux-5.19.y)).
|
||||
@@ -309,6 +310,22 @@ If you are curious how that works, please visit the [AppImage website](https://a
|
||||
|
||||
Notice: The connect commands allow
|
||||
|
||||
### Conda-forge
|
||||
|
||||
A [conda-forge feedstock for `nvtop`](https://github.com/conda-forge/nvtop-feedstock) is available.
|
||||
|
||||
#### conda / mamba / miniforge
|
||||
|
||||
```bash
|
||||
conda install --channel conda-forge nvtop
|
||||
```
|
||||
|
||||
#### pixi
|
||||
|
||||
```bash
|
||||
pixi global install nvtop
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
- NVIDIA drivers (same as above)
|
||||
|
||||
@@ -63,9 +63,11 @@ struct intel_process_info_cache {
|
||||
|
||||
struct gpu_info_intel {
|
||||
struct gpu_info base;
|
||||
enum { DRIVER_I915, DRIVER_XE } driver;
|
||||
|
||||
struct nvtop_device *card_device;
|
||||
struct nvtop_device *driver_device;
|
||||
struct nvtop_device *hwmon_device;
|
||||
struct intel_process_info_cache *last_update_process_cache, *current_update_process_cache; // Cached processes info
|
||||
};
|
||||
|
||||
@@ -113,10 +115,12 @@ void gpuinfo_intel_shutdown(void) {
|
||||
|
||||
const char *gpuinfo_intel_last_error_string(void) { return "Err"; }
|
||||
|
||||
static const char drm_intel_render[] = "drm-engine-render";
|
||||
static const char drm_intel_copy[] = "drm-engine-copy";
|
||||
static const char drm_intel_video[] = "drm-engine-video";
|
||||
static const char drm_intel_video_enhance[] = "drm-engine-video-enhance";
|
||||
static const char i915_drm_intel_render[] = "drm-engine-render";
|
||||
static const char i915_drm_intel_copy[] = "drm-engine-copy";
|
||||
static const char i915_drm_intel_video[] = "drm-engine-video";
|
||||
static const char i915_drm_intel_video_enhance[] = "drm-engine-video-enhance";
|
||||
|
||||
static const char xe_drm_intel_vram[] = "drm-total-vram0";
|
||||
|
||||
static bool parse_drm_fdinfo_intel(struct gpu_info *info, FILE *fdinfo_file, struct gpu_process *process_info) {
|
||||
struct gpu_info_intel *gpu_info = container_of(info, struct gpu_info_intel, base);
|
||||
@@ -150,12 +154,22 @@ static bool parse_drm_fdinfo_intel(struct gpu_info *info, FILE *fdinfo_file, str
|
||||
continue;
|
||||
client_id_set = true;
|
||||
} else {
|
||||
bool is_render = !strcmp(key, drm_intel_render);
|
||||
bool is_copy = !strcmp(key, drm_intel_copy);
|
||||
bool is_video = !strcmp(key, drm_intel_video);
|
||||
bool is_video_enhance = !strcmp(key, drm_intel_video_enhance);
|
||||
bool is_render = !strcmp(key, i915_drm_intel_render);
|
||||
bool is_copy = !strcmp(key, i915_drm_intel_copy);
|
||||
bool is_video = !strcmp(key, i915_drm_intel_video);
|
||||
bool is_video_enhance = !strcmp(key, i915_drm_intel_video_enhance);
|
||||
|
||||
if (strcmp(key, xe_drm_intel_vram)) {
|
||||
// TODO: do we count "gtt mem" too?
|
||||
unsigned long mem_int;
|
||||
char *endptr;
|
||||
|
||||
if (is_render || is_copy || is_video || is_video_enhance) {
|
||||
mem_int = strtoul(val, &endptr, 10);
|
||||
if (endptr == val || (strcmp(endptr, " kB") && strcmp(endptr, " KiB")))
|
||||
continue;
|
||||
|
||||
SET_GPUINFO_PROCESS(process_info, gpu_memory_usage, mem_int * 1024);
|
||||
} else if (is_render || is_copy || is_video || is_video_enhance) {
|
||||
char *endptr;
|
||||
uint64_t time_spent = strtoull(val, &endptr, 10);
|
||||
if (endptr == val || strcmp(endptr, " ns"))
|
||||
@@ -249,19 +263,21 @@ static void add_intel_cards(struct nvtop_device *dev, struct list_head *devices,
|
||||
struct nvtop_device *parent;
|
||||
if (nvtop_device_get_parent(dev, &parent) < 0)
|
||||
return;
|
||||
// Consider enabled Intel cards using the i915 driver
|
||||
// Consider enabled Intel cards using the i915 or xe driver
|
||||
const char *vendor, *driver, *enabled;
|
||||
if (nvtop_device_get_sysattr_value(parent, "vendor", &vendor) < 0 || strcmp(vendor, VENDOR_INTEL_STR))
|
||||
return;
|
||||
if (nvtop_device_get_driver(parent, &driver) < 0 || strcmp(driver, "i915"))
|
||||
if (nvtop_device_get_driver(parent, &driver) < 0 || (strcmp(driver, "i915") && strcmp(driver, "xe")))
|
||||
return;
|
||||
if (nvtop_device_get_sysattr_value(parent, "enable", &enabled) < 0 || strcmp(enabled, "1"))
|
||||
return;
|
||||
|
||||
struct gpu_info_intel *thisGPU = &gpu_infos[intel_gpu_count++];
|
||||
thisGPU->base.vendor = &gpu_vendor_intel;
|
||||
thisGPU->driver = !strcmp(driver, "xe") ? DRIVER_XE : DRIVER_I915;
|
||||
thisGPU->card_device = nvtop_device_ref(dev);
|
||||
thisGPU->driver_device = nvtop_device_ref(parent);
|
||||
thisGPU->hwmon_device = nvtop_device_get_hwmon(thisGPU->driver_device);
|
||||
const char *pdev_val;
|
||||
int retval = nvtop_device_get_property_value(thisGPU->driver_device, "PCI_SLOT_NAME", &pdev_val);
|
||||
assert(retval >= 0 && pdev_val != NULL && "Could not retrieve device PCI slot name");
|
||||
@@ -350,42 +366,41 @@ void gpuinfo_intel_refresh_dynamic_info(struct gpu_info *_gpu_info) {
|
||||
|
||||
RESET_ALL(dynamic_info->valid);
|
||||
|
||||
nvtop_device *card_dev_copy;
|
||||
// We are creating new devices because the device_get_sysattr_value caches its querries
|
||||
const char *syspath;
|
||||
nvtop_device_get_syspath(gpu_info->card_device, &syspath);
|
||||
nvtop_device_new_from_syspath(&card_dev_copy, syspath);
|
||||
nvtop_device *card_dev_noncached = NULL;
|
||||
if (nvtop_device_get_syspath(gpu_info->card_device, &syspath) >= 0)
|
||||
nvtop_device_new_from_syspath(&card_dev_noncached, syspath);
|
||||
nvtop_device *driver_dev_noncached = NULL;
|
||||
if (nvtop_device_get_syspath(gpu_info->driver_device, &syspath) >= 0)
|
||||
nvtop_device_new_from_syspath(&driver_dev_noncached, syspath);
|
||||
nvtop_device *hwmon_dev_noncached = NULL;
|
||||
if (gpu_info->hwmon_device) {
|
||||
if (nvtop_device_get_syspath(gpu_info->hwmon_device, &syspath) >= 0)
|
||||
nvtop_device_new_from_syspath(&hwmon_dev_noncached, syspath);
|
||||
}
|
||||
|
||||
nvtop_device *clock_device = gpu_info->driver == DRIVER_XE ? driver_dev_noncached : card_dev_noncached;
|
||||
// GPU clock
|
||||
const char *gt_cur_freq;
|
||||
if (nvtop_device_get_sysattr_value(card_dev_copy, "gt_cur_freq_mhz", >_cur_freq) >= 0) {
|
||||
const char *gt_cur_freq_sysattr = gpu_info->driver == DRIVER_XE ? "tile0/gt0/freq0/cur_freq" : "gt_cur_freq_mhz";
|
||||
if (nvtop_device_get_sysattr_value(clock_device, gt_cur_freq_sysattr, >_cur_freq) >= 0) {
|
||||
unsigned val = strtoul(gt_cur_freq, NULL, 10);
|
||||
SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed, val);
|
||||
}
|
||||
const char *gt_max_freq;
|
||||
if (nvtop_device_get_sysattr_value(card_dev_copy, "gt_max_freq_mhz", >_max_freq) >= 0) {
|
||||
const char *gt_max_freq_sysattr = gpu_info->driver == DRIVER_XE ? "tile0/gt0/freq0/max_freq" : "gt_max_freq_mhz";
|
||||
if (nvtop_device_get_sysattr_value(clock_device, gt_max_freq_sysattr, >_max_freq) >= 0) {
|
||||
unsigned val = strtoul(gt_max_freq, NULL, 10);
|
||||
SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed_max, val);
|
||||
}
|
||||
|
||||
// Mem clock
|
||||
// TODO: the attribute mem_cur_freq_mhz and mem_max_freq_mhz are speculative (not present on integrated graphics)
|
||||
const char *mem_cur_freq;
|
||||
if (nvtop_device_get_sysattr_value(card_dev_copy, "mem_cur_freq_mhz", &mem_cur_freq) >= 0) {
|
||||
unsigned val = strtoul(mem_cur_freq, NULL, 10);
|
||||
SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed, val);
|
||||
}
|
||||
const char *mem_max_freq;
|
||||
if (nvtop_device_get_sysattr_value(card_dev_copy, "mem_max_freq_mhz", &mem_max_freq) >= 0) {
|
||||
unsigned val = strtoul(mem_max_freq, NULL, 10);
|
||||
SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed, val);
|
||||
}
|
||||
|
||||
// TODO: find how to extract global utilization
|
||||
// gpu util will be computed as the sum of all the processes utilization for now
|
||||
|
||||
if (!static_info->integrated_graphics) {
|
||||
nvtop_pcie_link curr_link_characteristics;
|
||||
int ret = nvtop_device_current_pcie_link(card_dev_copy, &curr_link_characteristics);
|
||||
int ret = nvtop_device_current_pcie_link(driver_dev_noncached, &curr_link_characteristics);
|
||||
if (ret >= 0) {
|
||||
SET_GPUINFO_DYNAMIC(dynamic_info, pcie_link_width, curr_link_characteristics.width);
|
||||
unsigned pcieGen = nvtop_pcie_gen_from_link_speed(curr_link_characteristics.speed);
|
||||
@@ -394,8 +409,24 @@ void gpuinfo_intel_refresh_dynamic_info(struct gpu_info *_gpu_info) {
|
||||
}
|
||||
|
||||
// TODO: Attributes such as memory, fan, temperature, power info should be available once the hwmon patch lands
|
||||
if (hwmon_dev_noncached) {
|
||||
const char *hwmon_power;
|
||||
if (nvtop_device_get_sysattr_value(hwmon_dev_noncached, "power1", &hwmon_power) >= 0) {
|
||||
unsigned val = strtoul(hwmon_power, NULL, 10);
|
||||
SET_GPUINFO_DYNAMIC(dynamic_info, power_draw, val / 1000);
|
||||
}
|
||||
const char *hwmon_power_max;
|
||||
if (nvtop_device_get_sysattr_value(hwmon_dev_noncached, "power1_max", &hwmon_power_max) >= 0) {
|
||||
unsigned val = strtoul(hwmon_power_max, NULL, 10);
|
||||
SET_GPUINFO_DYNAMIC(dynamic_info, power_draw_max, val / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
nvtop_device_unref(card_dev_copy);
|
||||
// Let the temporary devices be garbage collected
|
||||
nvtop_device_unref(card_dev_noncached);
|
||||
nvtop_device_unref(driver_dev_noncached);
|
||||
if (hwmon_dev_noncached)
|
||||
nvtop_device_unref(hwmon_dev_noncached);
|
||||
}
|
||||
|
||||
static void swap_process_cache_for_next_update(struct gpu_info_intel *gpu_info) {
|
||||
|
||||
Reference in New Issue
Block a user