From f73af86a59a47aa35fe58c86ebb76e1fe313cc6d Mon Sep 17 00:00:00 2001 From: yulink Date: Fri, 10 Jul 2026 16:07:19 +0800 Subject: [PATCH] feat(ascend): support DDR memory and fix device enumeration for 310P3 - Add DDR memory fallback when HBM is unavailable (310P3/300i DUO) - Fix device enumeration: use physical card ID instead of array index - Fix per-process GPU utilization garbage values by zeroing process structs - Add memory_type static field to distinguish DDR vs HBM in display - Update TUI to show memory type (DDR 451MHz vs HBM xxxMHz) - Update JSON snapshot output with memory_type field --- include/nvtop/extract_gpuinfo_common.h | 2 + src/extract_gpuinfo_ascend.c | 68 ++++++++++++++++++++------ src/interface.c | 12 ++++- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/include/nvtop/extract_gpuinfo_common.h b/include/nvtop/extract_gpuinfo_common.h index 9e4d1c9d..a1b029c1 100644 --- a/include/nvtop/extract_gpuinfo_common.h +++ b/include/nvtop/extract_gpuinfo_common.h @@ -61,6 +61,7 @@ enum gpuinfo_static_info_valid { gpuinfo_l2cache_size_valid, gpuinfo_n_exec_engines_valid, gpuinfo_engine_count_valid, + gpuinfo_memory_type_valid, gpuinfo_static_info_count, }; @@ -78,6 +79,7 @@ struct gpuinfo_static_info { unsigned engine_count; bool integrated_graphics; bool encode_decode_shared; + char memory_type[8]; unsigned char valid[(gpuinfo_static_info_count + CHAR_BIT - 1) / CHAR_BIT]; }; diff --git a/src/extract_gpuinfo_ascend.c b/src/extract_gpuinfo_ascend.c index e8b15999..f91409e3 100644 --- a/src/extract_gpuinfo_ascend.c +++ b/src/extract_gpuinfo_ascend.c @@ -127,7 +127,7 @@ static bool gpuinfo_ascend_get_device_handles(struct list_head *devices, unsigne for (int i = 0; i < num_cards; ++i) { for (int j = 0; j < card_device_list[i]; ++j) { gpu_infos[*count].base.vendor = &gpu_vendor_ascend; - _encode_card_device_id_to_pdev(gpu_infos[*count].base.pdev, i, j); + _encode_card_device_id_to_pdev(gpu_infos[*count].base.pdev, card_list[i], j); list_add_tail(&gpu_infos[*count].base.list, devices); *count += 1; } @@ -163,7 +163,23 @@ static void gpuinfo_ascend_populate_static_info(struct gpu_info *_gpu_info) { SET_VALID(gpuinfo_device_name_valid, static_info->valid); } free(chip_info); - // todo: it seems that other static infos are not supported by Ascend DCMI for now, will add if possible in future + + /* Detect memory type: HBM (910B) vs DDR (310P3/300i DUO) */ + struct dsmi_hbm_info_stru hbm_info; + int detect_ret = dcmi_get_hbm_info(card_id, device_id, &hbm_info); + if (detect_ret == DCMI_SUCCESS) { + strncpy(static_info->memory_type, "HBM", sizeof(static_info->memory_type) - 1); + static_info->memory_type[sizeof(static_info->memory_type) - 1] = '\0'; + SET_VALID(gpuinfo_memory_type_valid, static_info->valid); + } else { + struct dcmi_memory_info_stru ddr_info; + detect_ret = dcmi_get_memory_info(card_id, device_id, &ddr_info); + if (detect_ret == DCMI_SUCCESS) { + strncpy(static_info->memory_type, "DDR", sizeof(static_info->memory_type) - 1); + static_info->memory_type[sizeof(static_info->memory_type) - 1] = '\0'; + SET_VALID(gpuinfo_memory_type_valid, static_info->valid); + } + } } static void gpuinfo_ascend_refresh_dynamic_info(struct gpu_info *_gpu_info) { @@ -188,11 +204,40 @@ static void gpuinfo_ascend_refresh_dynamic_info(struct gpu_info *_gpu_info) { SET_VALID(gpuinfo_gpu_clock_speed_max_valid, dynamic_info->valid); } - unsigned hbm_freq; - last_dcmi_return_status = dcmi_get_device_frequency(card_id, device_id, DCMI_FREQ_HBM, &hbm_freq); + /* Try HBM memory (Ascend 910B/910A) first, then DDR (Ascend 310P3/300i DUO) */ + struct dsmi_hbm_info_stru hbm_info; + last_dcmi_return_status = dcmi_get_hbm_info(card_id, device_id, &hbm_info); if (last_dcmi_return_status == DCMI_SUCCESS) { - dynamic_info->mem_clock_speed = hbm_freq; - SET_VALID(gpuinfo_mem_clock_speed_valid, dynamic_info->valid); + SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, hbm_info.memory_size * KB_TO_GB); + SET_GPUINFO_DYNAMIC(dynamic_info, used_memory, hbm_info.memory_usage * KB_TO_GB); + SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, (hbm_info.memory_size - hbm_info.memory_usage) * KB_TO_GB); + SET_GPUINFO_DYNAMIC(dynamic_info, mem_util_rate, hbm_info.memory_usage * 100 / hbm_info.memory_size); + + /* HBM memory clock */ + unsigned hbm_freq; + last_dcmi_return_status = dcmi_get_device_frequency(card_id, device_id, DCMI_FREQ_HBM, &hbm_freq); + if (last_dcmi_return_status == DCMI_SUCCESS) { + dynamic_info->mem_clock_speed = hbm_freq; + SET_VALID(gpuinfo_mem_clock_speed_valid, dynamic_info->valid); + } + } else { + /* Fallback to DDR memory (300i DUO / 310P3) */ + struct dcmi_memory_info_stru ddr_info; + last_dcmi_return_status = dcmi_get_memory_info(card_id, device_id, &ddr_info); + if (last_dcmi_return_status == DCMI_SUCCESS) { + /* memory_size is in MB, convert to bytes for nvtop */ + unsigned long long total_bytes = ddr_info.memory_size * 1024 * 1024; + unsigned long long used_bytes = total_bytes * ddr_info.utilize / 100; + SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, total_bytes); + SET_GPUINFO_DYNAMIC(dynamic_info, used_memory, used_bytes); + SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, total_bytes - used_bytes); + SET_GPUINFO_DYNAMIC(dynamic_info, mem_util_rate, ddr_info.utilize); + + if (ddr_info.freq > 0) { + dynamic_info->mem_clock_speed = ddr_info.freq; + SET_VALID(gpuinfo_mem_clock_speed_valid, dynamic_info->valid); + } + } } unsigned aicore_util_rate; @@ -202,15 +247,6 @@ static void gpuinfo_ascend_refresh_dynamic_info(struct gpu_info *_gpu_info) { SET_VALID(gpuinfo_gpu_util_rate_valid, dynamic_info->valid); } - struct dsmi_hbm_info_stru hbm_info; - last_dcmi_return_status = dcmi_get_hbm_info(card_id, device_id, &hbm_info); - if (last_dcmi_return_status == DCMI_SUCCESS) { - SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, hbm_info.memory_size * KB_TO_GB); - SET_GPUINFO_DYNAMIC(dynamic_info, used_memory, hbm_info.memory_usage * KB_TO_GB); - SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, (hbm_info.memory_size - hbm_info.memory_usage) * KB_TO_GB); - SET_GPUINFO_DYNAMIC(dynamic_info, mem_util_rate, hbm_info.memory_usage * 100 / hbm_info.memory_size); - } - int device_temperature; last_dcmi_return_status = dcmi_get_device_temperature(card_id, device_id, &device_temperature); if (last_dcmi_return_status == DCMI_SUCCESS) { @@ -241,6 +277,8 @@ static void gpuinfo_ascend_get_running_processes(struct gpu_info *_gpu_info) { perror("Could not allocate memory: "); exit(EXIT_FAILURE); } + // Zero-initialize to prevent garbage values for unset fields (e.g. gpu_usage) + memset(_gpu_info->processes, 0, _gpu_info->processes_array_size * sizeof(*_gpu_info->processes)); for (int i = 0; i < proc_num; i++) { _gpu_info->processes[i].type = gpu_process_compute; _gpu_info->processes[i].pid = proc_info[i].proc_id; diff --git a/src/interface.c b/src/interface.c index ae231991..ce3bdfe7 100644 --- a/src/interface.c +++ b/src/interface.c @@ -806,10 +806,12 @@ static void draw_devices(struct list_head *devices, struct nvtop_interface *inte // MEM CLOCK werase(dev->mem_clock_info); + const char *mem_label = GPUINFO_STATIC_FIELD_VALID(&device->static_info, memory_type) + ? device->static_info.memory_type : "MEM"; if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, mem_clock_speed)) - mvwprintw(dev->mem_clock_info, 0, 0, "MEM %uMHz", device->dynamic_info.mem_clock_speed); + mvwprintw(dev->mem_clock_info, 0, 0, "%s %uMHz", mem_label, device->dynamic_info.mem_clock_speed); else - mvwprintw(dev->mem_clock_info, 0, 0, "MEM N/A MHz"); + mvwprintw(dev->mem_clock_info, 0, 0, "%s N/A MHz", mem_label); mvwchgat(dev->mem_clock_info, 0, 0, 3, 0, cyan_color, NULL); wnoutrefresh(dev->mem_clock_info); @@ -2172,6 +2174,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); + // Memory Type + if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, memory_type)) + printf("%s\"memory_type\": \"%s\",\n", indent_level_four, device->static_info.memory_type); + else + printf("%s\"memory_type\": null,\n", indent_level_four); + // 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);