You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python调用的CUDA代码GPU性能分析方法咨询

针对你这个用Cython封装CUDA共享库、在Python项目里要监控GPU状态的需求,我整理了两种可行的方案,刚好对应你提到的两种思路,而且避开nvprof/nvvp的限制:

一、代码内集成性能监控(精准控制采样时机)

这种方式适合你需要精准监控特定代码段的场景,比如某个CUDA函数的实际内存吞吐量、显存占用变化,核心思路是在CUDA代码里调用NVIDIA提供的API获取状态,再通过Cython暴露给Python调用。

1. 基础显存状态查询

直接用CUDA Runtime API就能获取显存的使用情况,不需要额外依赖:

  • 先在CUDA代码里写对外暴露的C接口:
#include <cuda_runtime.h>

// 对外暴露的C接口,方便Cython调用
extern "C" {
void get_gpu_memory_stats(size_t* free_mem, size_t* total_mem) {
    cudaMemGetInfo(free_mem, total_mem);
}
}
  • 然后在Cython里封装这个接口:
# 声明CUDA函数
cdef extern from "gpu_monitor.h":
    void get_gpu_memory_stats(size_t* free_mem, size_t* total_mem)

def get_gpu_mem_usage():
    cdef size_t free_mem, total_mem
    get_gpu_memory_stats(&free_mem, &total_mem)
    used_mem = total_mem - free_mem
    # 转换为GB单位返回
    return {
        "free_gb": free_mem / (1024**3),
        "used_gb": used_mem / (1024**3),
        "total_gb": total_mem / (1024**3)
    }
  • 最后在Python项目里按需调用:
from your_cython_module import get_gpu_mem_usage

# 调用CUDA函数前获取状态
pre_stats = get_gpu_mem_usage()
print(f"CUDA操作前显存占用: {pre_stats['used_gb']:.2f} GB")

# 执行你的CUDA共享库调用
your_cuda_function()

# 调用后获取状态
post_stats = get_gpu_mem_usage()
print(f"CUDA操作后显存占用: {post_stats['used_gb']:.2f} GB")

2. 内存吞吐量与GPU利用率监控

如果需要更细致的指标比如内存吞吐量GPU利用率,可以用cudaEvent计时(测吞吐量)或者NVIDIA Management Library (NVML)(测利用率):

  • cudaEvent测H2D/D2H拷贝的吞吐量:
#include <cuda_runtime.h>

extern "C" {
float measure_h2d_throughput(void* host_ptr, void* dev_ptr, size_t data_size) {
    cudaEvent_t start, stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);

    cudaEventRecord(start);
    cudaMemcpy(dev_ptr, host_ptr, data_size, cudaMemcpyHostToDevice);
    cudaEventRecord(stop);
    cudaEventSynchronize(stop);

    float elapsed_ms;
    cudaEventElapsedTime(&elapsed_ms, start, stop);
    // 转换为GB/s
    float throughput = (data_size / (1024*1024*1024)) / (elapsed_ms / 1000);

    cudaEventDestroy(start);
    cudaEventDestroy(stop);
    return throughput;
}
}
  • 用NVML获取GPU利用率(需要链接NVML库,编译时加-lnvidia-ml):
#include <nvml.h>

extern "C" {
int get_gpu_utilization(unsigned int* gpu_util, unsigned int* mem_util) {
    // 初始化NVML
    if (nvmlInit() != NVML_SUCCESS) return -1;

    nvmlDevice_t device;
    // 获取第0块GPU的句柄(多GPU场景需要调整索引)
    if (nvmlDeviceGetHandleByIndex(0, &device) != NVML_SUCCESS) {
        nvmlShutdown();
        return -2;
    }

    nvmlUtilization_t util;
    if (nvmlDeviceGetUtilizationRates(device, &util) != NVML_SUCCESS) {
        nvmlShutdown();
        return -3;
    }

    *gpu_util = util.gpu;
    *mem_util = util.memory;

    nvmlShutdown();
    return 0;
}
}

把这些函数封装到Cython后,就能在Python里直接获取吞吐量和利用率,甚至可以开个后台线程定时采样,记录整个运行周期的状态变化。

二、独立持续监控工具(无需修改代码)

如果不想改动现有代码,只想全局监控整个Python项目运行期间的GPU状态,这些工具完全可以替代nvprof/nvvp:

  • nvidia-smi(官方自带):最基础的工具,持续刷新并记录状态:
    • 实时监控:nvidia-smi --loop=1(每秒刷新一次)
    • 记录到文件:nvidia-smi --loop=1 --format=csv --query-gpu=timestamp,utilization.gpu,memory.used,memory.total >> gpu_log.csv,事后可以用Python分析这个CSV文件。
  • nvtop:类似htop的GPU监控工具,界面直观,能看到每个进程的GPU占用、显存使用、温度等,安装后直接运行nvtop即可。
  • gpustat:轻量的Python工具,输出简洁,适合终端快速查看,安装命令pip install gpustat,实时监控用gpustat -i 1(每秒刷新)。

如果想让监控和Python代码联动(比如启动代码时自动开始监控,结束时自动停止),可以用Python的subprocess模块:

import subprocess
import time

# 启动nvidia-smi记录到日志文件
log_file = open("gpu_monitor.log", "w")
monitor_proc = subprocess.Popen(
    ["nvidia-smi", "--loop=1", "--format=csv", "--query-gpu=timestamp,utilization.gpu,memory.used"],
    stdout=log_file,
    stderr=subprocess.STDOUT
)

# 执行你的Python项目核心逻辑
run_your_large_python_project()

# 停止监控
monitor_proc.terminate()
log_file.close()

两种方式各有优劣:代码内集成适合精准定位特定函数的性能瓶颈,独立工具适合快速排查全局GPU负载问题,你可以根据需求选择~

内容的提问来源于stack exchange,提问作者phlegmax

火山引擎 最新活动