CUDA 2.5 GPU设备信息
我们在使用CUDA前要先确定当前的硬件环境,这使得我们的程序不那么容易因为设备不同而崩溃。
博客毕竟无法常常更新,所以这里会附上一些官方参考文档的链接供参考。一切实际内容以官方文档为准。
🔗 文档链接
CUDA TOOLKIT DOCUMENTATION: https://docs.nvidia.com/cuda/cuda-runtime-api/index.html
CUDA C++ Programming Guide: https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#
CUDA Toolkit Archive Document: https://developer.nvidia.com/cuda-toolkit-archive
一、设备查询API
在CUDA运行时API中有很多函数可以帮助管理这些设备。下列简单介绍几个相关API信息。
1、cudaSetDevice
cudaError_t cudaSetDevice(int device);
将当前线程所使用的“默认 CUDA 设备(GPU)”切换到编号为 device 的设备。之后所有没有显式指定设备的 CUDA 调用,都将在这个设备上执行。
在多 GPU 程序里,先调用 cudaGetDeviceCount 确定总设备数,再在不同线程/进程中用 cudaSetDevice 绑定到各自的 GPU。
确保每个 worker 只操作自己分配的显卡。
返回值:成功返回 cudaSuccess,否则返回相应错误码(如 cudaErrorInvalidDevice)。
2、cudaGetDeviceProperties
cudaError_t cudaGetDeviceProperties(cudaDeviceProp *prop, int device);
作用
查询编号为 device 的 GPU 硬件和架构信息,填充到 cudaDeviceProp 结构体中。
作用: 获取设备名称、总显存大小、计算能力(major/minor)、最大线程数、时钟频率等。
根据不同卡的能力动态调整 kernel 配置(如 block 大小、并行度)。
返回值
cudaSuccess 或错误码(如设备不存在)。
3、cudaDriverGetVersion
cudaError_t cudaDriverGetVersion(int *driverVersion);
作用: 获取当前系统上已安装的 NVIDIA 驱动(Driver)的版本号,结果以整数形式返回,格式为 1000主版本 + 10次版本,例如 11030 表示 11.3。
返回值: cudaSuccess 或错误码。
4、cudaRuntimeGetVersion
cudaError_t cudaRuntimeGetVersion(int *runtimeVersion);
作用: 获取当前链接的 CUDA Runtime 库的版本号,格式同驱动版本。
验证运行时(Runtime)API 版本,确保与编译时/驱动端兼容。
区分不同特性是否可用(如新引入的 API 支持)。
返回值: cudaSuccess 或错误码。
有关更多API使用方式请参考官方的文档
附录中给出了查询设备信息的详细代码,运行后输出信息类似下列输出:
./checkDeviceInfor Starting...
Detected 1 CUDA Capable device(s)
Device 0: "NVIDIA GeForce RTX 3070 Laptop GPU"
CUDA Driver Version / Runtime Version 12.7 / 11.6
CUDA Capability Major/Minor version number: 8.6
Total amount of global memory: 8.00 GBytes (8589410304 bytes)
GPU Clock rate: 1560 MHz (1.56 GHz)
Memory Clock rate: 7001 Mhz
Memory Bus Width: 256-bit
L2 Cache Size: 4194304 bytes
Max Texture Dimension Size (x,y,z) 1D=(131072), 2D=(131072,65536), 3D=(16384,16384,16384)
Max Layered Texture Size (dim) x layers 1D=(32768) x 2048, 2D=(32768,32768) x 2048
Total amount of constant memory: 65536 bytes
Total amount of shared memory per block: 49152 bytes
Total number of registers available per block: 65536
Warp size: 32
Maximum number of threads per multiprocessor: 1536
Maximum number of threads per block: 1024
Maximum sizes of each dimension of a block: 1024 x 1024 x 64
Maximum sizes of each dimension of a grid: 2147483647 x 65535 x 65535
Maximum memory pitch: 2147483647 bytes
命令行查询工具
nvidia-smi
nvidia-smi是nvidia驱动程序内带的一个工具,可以返回当前环境的设备信息:
>nvidia-smi
Fri Jun 20 16:55:26 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 566.07 Driver Version: 566.07 CUDA Version: 12.7 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Driver-Model | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 3070 ... WDDM | 00000000:01:00.0 On | N/A |
| N/A 52C P8 20W / 134W | 364MiB / 8192MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
+-----------------------------------------------------------------------------------------+
如果在linux系统里,可以通过添加watch
命令来获取及时最新的信息:
watch -n 1 nvidia-smi
该工具可以通过添加不同参数来取得不同的信息,如添加-L
可以得到完整的显卡信息:
>nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 3070 Laptop GPU (UUID: GPU-fxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
你还可以使用nvidia-smi -q -i x
的方式查阅详细信息(-i
后接整形数字,指代查询对应序号的显卡),并可以跟上-d xx
参数来查阅个别信息。可查阅的信息有:
- MEMORY
- UTILIZATION
- ECC
- TEMPERATURE
- POWER
- CLOCK
- COMPUTE
- PIDS
- PERFORMANCE
- SUPPORTED_CLOCKS
- PAGE_RETIREMENT
- ACCOUNTING
如可以使用这个指令查阅第一张显卡的显存情况:
>nvidia-smi -q -i 0 -d MEMORY
==============NVSMI LOG==============
Timestamp : Fri Jun 20 17:12:43 2025
Driver Version : 566.07
CUDA Version : 12.7
Attached GPUs : 1
GPU 00000000:01:00.0
FB Memory Usage
Total : 8192 MiB
Reserved : 172 MiB
Used : 364 MiB
Free : 7657 MiB
BAR1 Memory Usage
Total : 8192 MiB
Used : 8164 MiB
Free : 28 MiB
Conf Compute Protected Memory Usage
Total : N/A
Used : N/A
Free : N/A
其他功能请参阅英伟达官方文档
nvitop
除此之外,我们可以像linux系统中的top命令一样观察显卡的实时占用情况。nvitop
这款工具是用python编写的工具,所以需要用到python环境。
官方文档提供了五种安装方式(但其实你可以直接用pip工具进行安装)
使用pipx进行安装pipx run nvitop
使用pip3进行安装pip3 install --upgrade nvitop
使用conda进行安装conda install -c conda-forge nvitop
从Github拉取最新版本进行安装pip3 install git+https://github.com/XuehaiPan/nvitop.git#egg=nvitop
clone项目并手动安装
git clone --depth=1 https://github.com/XuehaiPan/nvitop.git
cd nvitop
pip3 install .
将监控信息写入Tensorboard中:
import os
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.tensorboard import SummaryWriter
from nvitop import CudaDevice, ResourceMetricCollector
from nvitop.callbacks.tensorboard import add_scalar_dict
# Build networks and prepare datasets
...
# Logger and status collector
writer = SummaryWriter()
collector = ResourceMetricCollector(devices=CudaDevice.all(), # log all visible CUDA devices and use the CUDA ordinal
root_pids={os.getpid()}, # only log the descendant processes of the current process
interval=1.0) # snapshot interval for background daemon thread
# Start training
global_step = 0
for epoch in range(num_epoch):
with collector(tag='train'):
for batch in train_dataset:
with collector(tag='batch'):
metrics = train(net, batch)
global_step += 1
add_scalar_dict(writer, 'train', metrics, global_step=global_step)
add_scalar_dict(writer, 'resources', # tag='resources/train/batch/...'
collector.collect(),
global_step=global_step)
add_scalar_dict(writer, 'resources', # tag='resources/train/...'
collector.collect(),
global_step=epoch)
with collector(tag='validate'):
metrics = validate(net, validation_dataset)
add_scalar_dict(writer, 'validate', metrics, global_step=epoch)
add_scalar_dict(writer, 'resources', # tag='resources/validate/...'
collector.collect(),
global_step=epoch)
附录
0/头文件定义代码
#define CHECK(call) \
{ \
const cudaError_t error = call; \
if (error != cudaSuccess) \
{ \
fprintf(stderr, "Error: %s:%d, ", __FILE__, __LINE__); \
fprintf(stderr, "code: %d, reason: %s\n", error, \
cudaGetErrorString(error)); \
exit(1); \
} \
}
1/完整代码
#include "../common/common.h"
#include <cuda_runtime.h>
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%s Starting...\n", argv[0]);
int deviceCount = 0;
cudaGetDeviceCount(&deviceCount);
if (deviceCount == 0)
{
printf("There are no available device(s) that support CUDA\n");
}
else
{
printf("Detected %d CUDA Capable device(s)\n", deviceCount);
}
// 声明变量,dev 用于指定 GPU 设备编号,初始化为 0 ,driverVersion 和 runtimeVersion 分别用于存储 CUDA 驱动和运行时版本
int dev = 0, driverVersion = 0, runtimeVersion = 0;
// 调用 cudaSetDevice 函数设置当前使用的 GPU 设备为编号 dev 的设备
// CHECK 宏用于检查 CUDA 函数调用是否成功
CHECK(cudaSetDevice(dev));
// 声明一个 cudaDeviceProp 结构体变量 deviceProp,用于存储 GPU 设备的属性信息
cudaDeviceProp deviceProp;
// 调用 cudaGetDeviceProperties 函数获取编号为 dev 的 GPU 设备的属性信息,并存储到 deviceProp 中
CHECK(cudaGetDeviceProperties(&deviceProp, dev));
// 打印输出 GPU 设备的编号和名称
printf("Device %d: \"%s\"\n", dev, deviceProp.name);
// 调用 cudaDriverGetVersion 函数获取 CUDA 驱动版本,并存储到 driverVersion 中
cudaDriverGetVersion(&driverVersion);
// 调用 cudaRuntimeGetVersion 函数获取 CUDA 运行时版本,并存储到 runtimeVersion 中
cudaRuntimeGetVersion(&runtimeVersion);
// 打印输出 CUDA 驱动版本和运行时版本,通过整数除法和取余操作将版本号转换为 x.y 的形式
printf(" CUDA Driver Version / Runtime Version %d.%d / %d.%d\n",
driverVersion / 1000, (driverVersion % 100) / 10,
runtimeVersion / 1000, (runtimeVersion % 100) / 10);
// 打印输出 GPU 设备的计算能力主版本号和次版本号
printf(" CUDA Capability Major/Minor version number: %d.%d\n",
deviceProp.major, deviceProp.minor);
// 计算 GPU 设备的总全局内存容量(以 GBytes 为单位),并将结果和以字节为单位的值一起打印输出
printf(" Total amount of global memory: %.2f GBytes (%llu "
"bytes)\n", (float)deviceProp.totalGlobalMem / pow(1024.0, 3),
(unsigned long long)deviceProp.totalGlobalMem);
// 计算 GPU 设备的时钟速率(以 MHz 和 GHz 为单位),并打印输出
printf(" GPU Clock rate: %.0f MHz (%0.2f "
"GHz)\n", deviceProp.clockRate * 1e-3f,
deviceProp.clockRate * 1e-6f);
// 计算 GPU 设备的显存时钟速率(以 MHz 为单位),并打印输出
printf(" Memory Clock rate: %.0f Mhz\n",
deviceProp.memoryClockRate * 1e-3f);
// 打印输出 GPU 设备的显存总线宽度
printf(" Memory Bus Width: %d-bit\n",
deviceProp.memoryBusWidth);
// 判断 GPU 设备的 L2 缓存大小是否大于 0
if (deviceProp.l2CacheSize)
{
// 如果大于 0,则打印输出 L2 缓存大小
printf(" L2 Cache Size: %d bytes\n",
deviceProp.l2CacheSize);
}
// 打印输出 GPU 设备支持的最大纹理维度尺寸(1D、2D 和 3D)
printf(" Max Texture Dimension Size (x,y,z) 1D=(%d), "
"2D=(%d,%d), 3D=(%d,%d,%d)\n", deviceProp.maxTexture1D,
deviceProp.maxTexture2D[0], deviceProp.maxTexture2D[1],
deviceProp.maxTexture3D[0], deviceProp.maxTexture3D[1],
deviceProp.maxTexture3D[2]);
// 打印输出 GPU 设备支持的最大分层纹理尺寸(1D 和 2D)及其对应的层数
printf(" Max Layered Texture Size (dim) x layers 1D=(%d) x %d, "
"2D=(%d,%d) x %d\n", deviceProp.maxTexture1DLayered[0],
deviceProp.maxTexture1DLayered[1], deviceProp.maxTexture2DLayered[0],
deviceProp.maxTexture2DLayered[1],
deviceProp.maxTexture2DLayered[2]);
// 打印输出 GPU 设备的总常量内存大小
printf(" Total amount of constant memory: %lu bytes\n",
deviceProp.totalConstMem);
// 打印输出 GPU 设备每个块可使用的共享内存大小
printf(" Total amount of shared memory per block: %lu bytes\n",
deviceProp.sharedMemPerBlock);
// 打印输出 GPU 设备每个块可用的寄存器数量
printf(" Total number of registers available per block: %d\n",
deviceProp.regsPerBlock);
// 打印输出 GPU 设备的 warp 大小
printf(" Warp size: %d\n",
deviceProp.warpSize);
// 打印输出 GPU 设备每个 multiprocessor 上可支持的最大线程数
printf(" Maximum number of threads per multiprocessor: %d\n",
deviceProp.maxThreadsPerMultiProcessor);
// 打印输出 GPU 设备每个块可支持的最大线程数
printf(" Maximum number of threads per block: %d\n",
deviceProp.maxThreadsPerBlock);
// 打印输出 GPU 设备每个块在各个维度上的最大线程数
printf(" Maximum sizes of each dimension of a block: %d x %d x %d\n",
deviceProp.maxThreadsDim[0],
deviceProp.maxThreadsDim[1],
deviceProp.maxThreadsDim[2]);
// 打印输出 GPU 设备每个网格在各个维度上的最大尺寸
printf(" Maximum sizes of each dimension of a grid: %d x %d x %d\n",
deviceProp.maxGridSize[0],
deviceProp.maxGridSize[1],
deviceProp.maxGridSize[2]);
// 打印输出 GPU 设备支持的最大内存映射大小
printf(" Maximum memory pitch: %lu bytes\n",
deviceProp.memPitch);
// 正常退出程序,返回状态码 EXIT_SUCCESS 表示程序成功执行
exit(EXIT_SUCCESS);
}