diff --git a/include/nvtop/extract_gpuinfo_common.h b/include/nvtop/extract_gpuinfo_common.h index 9e4d1c9d..2366de06 100644 --- a/include/nvtop/extract_gpuinfo_common.h +++ b/include/nvtop/extract_gpuinfo_common.h @@ -53,6 +53,7 @@ #define GPUINFO_STATIC_FIELD_VALID(structPtr, field) VALUE_IS_VALID(structPtr, field, gpuinfo_) enum gpuinfo_static_info_valid { gpuinfo_device_name_valid = 0, + gpuinfo_device_architecture_valid, gpuinfo_max_pcie_gen_valid, gpuinfo_max_pcie_link_width_valid, gpuinfo_temperature_shutdown_threshold_valid, @@ -68,6 +69,7 @@ enum gpuinfo_static_info_valid { struct gpuinfo_static_info { char device_name[MAX_DEVICE_NAME]; + char device_architecture[MAX_DEVICE_NAME]; unsigned max_pcie_gen; unsigned max_pcie_link_width; unsigned temperature_shutdown_threshold; diff --git a/src/extract_gpuinfo_amdgpu.c b/src/extract_gpuinfo_amdgpu.c index a548cda0..c3a32ea9 100644 --- a/src/extract_gpuinfo_amdgpu.c +++ b/src/extract_gpuinfo_amdgpu.c @@ -600,6 +600,104 @@ static void gpuinfo_amdgpu_populate_static_info(struct gpu_info *_gpu_info) { } } + if (info_query_success) { + const char *arch_name = NULL; + switch (info.family_id) { +#ifdef AMDGPU_FAMILY_SI + case AMDGPU_FAMILY_SI: + arch_name = "GCN 1"; + break; +#endif +#ifdef AMDGPU_FAMILY_CI + case AMDGPU_FAMILY_CI: + arch_name = "GCN 2"; + break; +#endif +#ifdef AMDGPU_FAMILY_KV + case AMDGPU_FAMILY_KV: + arch_name = "GCN 2"; + break; +#endif +#ifdef AMDGPU_FAMILY_VI + case AMDGPU_FAMILY_VI: + arch_name = "GCN 3"; + break; +#endif +#ifdef AMDGPU_FAMILY_CZ + case AMDGPU_FAMILY_CZ: + arch_name = "GCN 3"; + break; +#endif +#ifdef AMDGPU_FAMILY_AI + case AMDGPU_FAMILY_AI: + arch_name = "GCN 5 (Vega)"; + break; +#endif +#ifdef AMDGPU_FAMILY_RV + case AMDGPU_FAMILY_RV: + arch_name = "GCN 5 (Vega)"; + break; +#endif +#ifdef AMDGPU_FAMILY_NV + case AMDGPU_FAMILY_NV: + arch_name = "RDNA"; + break; +#endif +#ifdef AMDGPU_FAMILY_VGH + case AMDGPU_FAMILY_VGH: + arch_name = "RDNA 2"; + break; +#endif +#ifdef AMDGPU_FAMILY_YC + case AMDGPU_FAMILY_YC: + arch_name = "RDNA 2"; + break; +#endif +#ifdef AMDGPU_FAMILY_GC_10_3_6 + case AMDGPU_FAMILY_GC_10_3_6: + arch_name = "RDNA 2"; + break; +#endif +#ifdef AMDGPU_FAMILY_GC_10_3_7 + case AMDGPU_FAMILY_GC_10_3_7: + arch_name = "RDNA 2"; + break; +#endif +#ifdef AMDGPU_FAMILY_GC_11_0_0 + case AMDGPU_FAMILY_GC_11_0_0: + arch_name = "RDNA 3"; + break; +#endif +#ifdef AMDGPU_FAMILY_GC_11_0_1 + case AMDGPU_FAMILY_GC_11_0_1: + arch_name = "RDNA 3"; + break; +#endif +#ifdef AMDGPU_FAMILY_GC_11_5_0 + case AMDGPU_FAMILY_GC_11_5_0: + arch_name = "RDNA 3.5"; + break; +#endif +#ifdef AMDGPU_FAMILY_GC_12_0_0 + case AMDGPU_FAMILY_GC_12_0_0: + arch_name = "RDNA 4"; + break; +#endif +#ifdef AMDGPU_FAMILY_GC_12_0_1 + case AMDGPU_FAMILY_GC_12_0_1: + arch_name = "RDNA 4"; + break; +#endif + default: + break; + } + if (arch_name) { + strncpy(static_info->device_architecture, arch_name, MAX_DEVICE_NAME - 1); + static_info->device_architecture[MAX_DEVICE_NAME - 1] = '\0'; + SET_VALID(gpuinfo_device_architecture_valid, static_info->valid); + } + } + // Retrieve infos from sysfs. // 1) Fan diff --git a/src/extract_gpuinfo_nvidia.c b/src/extract_gpuinfo_nvidia.c index 33670a60..a9aa5980 100644 --- a/src/extract_gpuinfo_nvidia.c +++ b/src/extract_gpuinfo_nvidia.c @@ -53,6 +53,8 @@ static const char *(*nvmlErrorString)(nvmlReturn_t); static nvmlReturn_t (*nvmlDeviceGetName)(nvmlDevice_t device, char *name, unsigned int length); +static nvmlReturn_t (*nvmlDeviceGetArchitecture)(nvmlDevice_t device, unsigned int *arch); + typedef struct { char busIdLegacy[16]; unsigned int domain; @@ -352,6 +354,9 @@ static bool gpuinfo_nvidia_init(void) { if (!nvmlDeviceGetName) goto init_error_clean_exit; + // Optional; not present in older drivers, absence is not an error + nvmlDeviceGetArchitecture = dlsym(libnvidia_ml_handle, "nvmlDeviceGetArchitecture"); + nvmlDeviceGetPciInfo = dlsym(libnvidia_ml_handle, "nvmlDeviceGetPciInfo_v3"); if (!nvmlDeviceGetPciInfo) nvmlDeviceGetPciInfo = dlsym(libnvidia_ml_handle, "nvmlDeviceGetPciInfo_v2"); @@ -560,6 +565,49 @@ static void gpuinfo_nvidia_populate_static_info(struct gpu_info *_gpu_info) { if (last_nvml_return_status == NVML_SUCCESS) SET_VALID(gpuinfo_device_name_valid, static_info->valid); + if (nvmlDeviceGetArchitecture) { + unsigned int arch = 0; + if (nvmlDeviceGetArchitecture(device, &arch) == NVML_SUCCESS) { + const char *arch_name = NULL; + switch (arch) { + case 2: + arch_name = "Kepler"; + break; + case 3: + arch_name = "Maxwell"; + break; + case 4: + arch_name = "Pascal"; + break; + case 5: + arch_name = "Volta"; + break; + case 6: + arch_name = "Turing"; + break; + case 7: + arch_name = "Ampere"; + break; + case 8: + arch_name = "Ada"; + break; + case 9: + arch_name = "Hopper"; + break; + case 10: + arch_name = "Blackwell"; + break; + default: + break; + } + if (arch_name) { + strncpy(static_info->device_architecture, arch_name, MAX_DEVICE_NAME - 1); + static_info->device_architecture[MAX_DEVICE_NAME - 1] = '\0'; + SET_VALID(gpuinfo_device_architecture_valid, static_info->valid); + } + } + } + last_nvml_return_status = nvmlDeviceGetMaxPcieLinkGeneration(device, &static_info->max_pcie_gen); if (last_nvml_return_status == NVML_SUCCESS) SET_VALID(gpuinfo_max_pcie_gen_valid, static_info->valid); diff --git a/src/interface.c b/src/interface.c index ae231991..67058b5c 100644 --- a/src/interface.c +++ b/src/interface.c @@ -2153,6 +2153,7 @@ void print_snapshot(struct list_head *devices, bool use_fahrenheit_option, bool const char *indent_level_eight = " "; const char *device_name_field = "device_name"; + const char *device_architecture_field = "device_architecture"; const char *gpu_clock_field = "gpu_clock"; const char *mem_clock_field = "mem_clock"; const char *temp_field = "temp"; @@ -2172,6 +2173,12 @@ void print_snapshot(struct list_head *devices, bool use_fahrenheit_option, bool else printf("%s\"%s\": null,\n", indent_level_four, device_name_field); + // Device Architecture + if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, device_architecture)) + printf("%s\"%s\": \"%s\",\n", indent_level_four, device_architecture_field, device->static_info.device_architecture); + else + printf("%s\"%s\": null,\n", indent_level_four, device_architecture_field); + // GPU Clock Speed if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, gpu_clock_speed)) printf("%s\"%s\": \"%uMHz\",\n", indent_level_four, gpu_clock_field, device->dynamic_info.gpu_clock_speed);