如何精准测量使用OpenACC+托管内存的GPU内存占用?
OpenACC托管内存应用的GPU内存占用精准测量方法
问题背景
对于使用OpenACC与Managed Memory(统一内存)的应用,如何精准测量GPU内存占用?同时存在两个疑问:
- nvidia-smi输出中上方的
10322MiB / 16160MiB与进程./myapp对应的398MiB内存数值有何差异? - 自定义
measure_acc_mem_usage函数与nvidia-smi的测量结果差异极大(如函数显示2GB,nvidia-smi显示16GB),且均与GPU内存饱和时的实际运行表现不符。
附用户提供的nvidia-smi输出:
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 510.85.02 Driver Version: 510.85.02 CUDA Version: 11.6 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 Tesla v100 ... Off | 00000000:01:00.0 Off | N/A | | N/A 51C P5 11W / N/A | 10322MiB / 16160MiB | 65% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | 0 N/A N/A 2670 G ./myapp 398MiB | +-----------------------------------------------------------------------------+
自定义测量函数:
void measure_acc_mem_usage() { auto dev_ty = acc_get_device_type(); auto dev_mem = acc_get_property(0, dev_ty, acc_property_memory); auto dev_free_mem = acc_get_property(0, dev_ty, acc_property_free_memory); auto mem = dev_mem - dev_free_mem; if (mem > max_mem_usage) max_mem_usage = mem; }
一、nvidia-smi内存数值差异解析
- 顶部总内存统计:
10322MiB / 16160MiB是GPU的全局已用显存/总显存,包含所有进程的显存占用、CUDA驱动上下文、后台系统进程,以及未被回收的显存碎片等所有GPU侧的内存消耗。 - 进程级内存统计:
398MiB是该进程当前实际驻留在GPU上的显式分配内存。但对于Managed Memory来说,这个数值仅统计已迁移到GPU的那部分托管内存,不包含仍在CPU端或尚未触发迁移的内存,且nvidia-smi对统一内存的统计存在延迟,无法实时反映动态迁移的内存变化。
二、自定义OpenACC函数的局限性
measure_acc_mem_usage无法准确统计托管内存的GPU占用,原因如下:
- 内存管理主体不匹配:托管内存由CUDA统一内存管理器负责分配和迁移,而非OpenACC runtime的内存池。
acc_property_free_memory仅统计OpenACC自身管理的内存池剩余空间,不包含CUDA统一内存占用的显存。 - 设备类型可能错误:如果
acc_get_device_type未显式指定为acc_device_nvidia或当前未正确绑定到GPU设备,可能获取的是CPU端的内存信息,导致数值完全失真。
三、精准测量的可行方法
1. 使用CUDA统一内存API
直接调用CUDA的cudaMemGetInfo函数,可准确统计整个GPU的已用/可用显存,包含托管内存实际驻留的部分:
#include <cuda_runtime.h> void measure_gpu_mem_usage() { size_t free_mem, total_mem; cudaError_t err = cudaMemGetInfo(&free_mem, &total_mem); if (err != cudaSuccess) return; // 处理错误 size_t used_mem = total_mem - free_mem; if (used_mem > max_mem_usage) max_mem_usage = used_mem; }
注意需在GPU上下文生效的位置调用(如OpenACC并行区域内,或提前通过cudaSetDevice(0)绑定设备)。
2. 使用NVProf/Nsight Systems工具
- NVProf:通过命令行采样实时GPU内存占用,包含统一内存的迁移活动:
nvprof --metrics gpu_memory_usage ./myapp - Nsight Systems:可视化性能分析工具,可直观查看不同时间段内GPU内存的动态变化,包括托管内存的分页、迁移细节,便于定位峰值占用点。
补充注意事项
- 托管内存是按需迁移的,GPU内存占用动态变化,单次测量无法反映峰值,需多次采样或使用工具持续监控。
- 若使用OpenACC显式数据管理(如
acc_copyin/acc_copyout),acc_get_property的结果会更准确,但该场景下不适用托管内存。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

