CUDA获取GPU的硬件信息
- 1. 获取GPU硬件信息
- 2. 常见硬件参数的含义和功能
在GPU加速计算和深度学习应用中,了解GPU硬件参数对于性能优化和资源分配至关重要。不同的GPU型号具有不同的计算能力、内存配置和架构特性,这些因素直接影响应用程序的性能表现。本文将详细介绍如何通过CUDA编程获取GPU硬件信息,并解释各项参数的意义和应用场景。
1. 获取GPU硬件信息
1.1. 实现方案
获取GPU硬件信息,主要通过以下几个接口来实现。
cudaGetDeviceCount:获取当前系统中可用的GPU设备数量。cudaGetDeviceProperties:获取指定GPU设备的基础信息,如设备名称、计算能力、全局内存大小等。cudaDeviceGetAttribute:获取指定GPU设备的高级信息,如核心时钟频率、内存时钟频率。
1.2. 完整源代码
#include <cuda_runtime.h>
#include <iostream>
#include <iomanip>
void getDeviceBaseProperties(int deviceIdx) {
// 使用cudaGetDeviceProperties获取基础信息
cudaDeviceProp prop;
cudaGetDeviceProperties(&prop, deviceIdx);
std::cout << " --------------- GPU设备基础信息 ---------------" << std::endl;
std::cout << " 设备名称: " << prop.name << std::endl;
std::cout << " 计算能力: " << prop.major << "." << prop.minor << std::endl;
std::cout << " 全局内存(显存): " << prop.totalGlobalMem / (1024 * 1024 * 1024.0) << " GB" << std::endl;
std::cout << " 流多处理器(SM)数量: " << prop.multiProcessorCount << std::endl;
std::cout << " 线程束大小: " << prop.warpSize << std::endl;
std::cout << " 每个块的最大线程数: " << prop.maxThreadsPerBlock << std::endl;
std::cout << " 每个块的共享内存: " << prop.sharedMemPerBlock / 1024 << " KB" << std::endl;
std::cout << " L2缓存大小: " << prop.l2CacheSize / 1024 << " KB" << std::endl;
std::cout << " 内存总线宽度: " << prop.memoryBusWidth << " bit" << std::endl;
std::cout << " ECC支持: " << (prop.ECCEnabled ? "是" : "否") << std::endl;
std::cout << " 统一地址空间: " << (prop.unifiedAddressing ? "是" : "否") << std::endl;
std::cout << " 托管内存支持: " << (prop.managedMemory ? "是" : "否") << std::endl;
std::cout << " 并发内核执行: " << (prop.concurrentKernels ? "是" : "否") << std::endl;
}
void getDeviceAdvancedProperties(int deviceIdx)
{
// 使用cudaDeviceGetAttribute获取高级信息
std::cout << " --------------- GPU设备高级信息 ---------------" << std::endl;
int attrValue;
cudaDeviceGetAttribute(&attrValue, cudaDevAttrClockRate, deviceIdx);
std::cout << " 核心时钟频率: " << attrValue / 1000 << " MHz" << std::endl;
cudaDeviceGetAttribute(&attrValue, cudaDevAttrMemoryClockRate, deviceIdx);
std::cout << " 内存时钟频率: " << attrValue / 1000 << " MHz" << std::endl;
cudaDeviceGetAttribute(&attrValue, cudaDevAttrGlobalMemoryBusWidth, deviceIdx);
std::cout << " 内存总线宽度: " << attrValue << " bits" << std::endl;
}
int main() {
// 获取GPU设备数量
int deviceCount;
cudaGetDeviceCount(&deviceCount);
if (deviceCount == 0) {
std::cout << "未找到可用的CUDA设备" << std::endl;
return 0;
}
for (int deviceIdx = 0; deviceIdx < deviceCount; deviceIdx++) {
std::cout << "【设备 " << deviceIdx << "】:" << std::endl;
// 基础信息
getDeviceBaseProperties(deviceIdx);
// 高级信息
getDeviceAdvancedProperties(deviceIdx);
}
return 0;
}
1.3. 编译和运行
# 编译
nvcc ./get_device_info.cu
# 运行
./a.out
【设备 0】:
--------------- GPU设备基础信息 ---------------
设备名称: NVIDIA GeForce RTX 3060
计算能力: 8.6
全局内存(显存): 11.9994 GB
流多处理器(SM)数量: 28
线程束大小: 32
每个块的最大线程数: 1024
每个块的共享内存: 48 KB
L2缓存大小: 2304 KB
内存总线宽度: 192 bit
ECC支持: 否
统一地址空间: 是
托管内存支持: 是
并发内核执行: 是
--------------- GPU设备高级信息 ---------------
核心时钟频率: 1777 MHz
内存时钟频率: 7501 MHz
内存总线宽度: 192 bits
1.4. cudaGetDeviceProperties与cudaDeviceGetAttribute的区别
在CUDA编程中,cudaGetDeviceProperties和cudaDeviceGetAttribute都是用于获取GPU设备信息的重要函数,但它们在使用方式、功能和适用场景上有显著区别。
1.4.1. 函数原型
cudaGetDeviceProperties:
cudaError_t cudaGetDeviceProperties(cudaDeviceProp* prop, int device);
- 一次性获取设备的所有属性
- 返回完整的
cudaDeviceProp结构体
cudaDeviceGetAttribute:
cudaError_t cudaDeviceGetAttribute(int* value, cudaDeviceAttr attr, int device);
- 获取设备的单个特定属性
- 需要指定要查询的属性枚举值
1.4.2. 核心区别
| 特性 | cudaGetDeviceProperties | cudaDeviceGetAttribute |
|---|---|---|
| 核心功能 | 一次性获取设备的所有属性 | 获取设备的单个特定属性 |
| 类型支持 | 支持多种不同的数据类型,如char[]字符串、int整数、int数组等 | 只能返回int类型的属性值 |
| 内存开销 | 较大(整个结构体) | 很小(单个整数) |
| 兼容性 | 较差,有些新的属性值不支持 | 较好 |
| 使用场景 | 1. 在程序初始化时一次性获取所有需要的设备信息 2. 获取基础设备信息 | 1. 程序运行时查询特定设备属性 2. 获取设备的高级(新增的)属性 |
1.4.3. 相互关系
cudaGetDeviceProperties 和 cudaDeviceGetAttribute 获取的设备属性有重叠的部分,也有不同的部分。
- 重叠的部分: 如cudaDevAttrGlobalMemoryBusWidth对应cudaDeviceProp的memoryBusWidth,更多的属性对应关系参见2.2小节:cudaDeviceAttr枚举详解。
- 不同的部分:
- 如cudaGetDeviceProperties可以获取设备型号,cudaDeviceGetAttribute不支持。
- cudaDeviceGetAttribute新增的属性,cudaDeviceProp可能不支持。
2. 常见硬件参数的含义和功能
2.1. cudaDeviceProp结构体字段详解
cudaDeviceProp结构体是CUDA编程中获取GPU硬件信息的关键数据结构,它包含了设备的完整属性信息。下面我将详细解释每个字段的含义及其对应的硬件参数功能。
2.1.1. 基本设备信息
char name[256]
- 含义:设备名称的ASCII字符串标识
- 硬件参数:GPU型号名称(如"NVIDIA GeForce RTX 4090")
- 功能:识别具体的GPU型号和制造商
- 应用场景:设备选择、日志记录、性能报告
cudaUUID_t uuid
- 含义:16字节的唯一设备标识符
- 硬件参数:设备的全局唯一ID
- 功能:在多GPU系统中唯一标识每个设备
- 应用场景:设备持久性识别、多GPU系统管理
size_t totalGlobalMem
- 含义:设备全局内存总大小(字节)
- 硬件参数:GPU显存容量
- 功能:存储需要处理的数据和中间结果
- 应用场景:内存分配决策、数据分块策略
2.1.2. 计算架构相关参数
int major 和 int minor
- 含义:主次计算能力版本号
- 硬件参数:GPU架构世代(如8.0代表Ampere架构)
- 功能:确定支持的CUDA功能和指令集
- 应用场景:功能兼容性检查、代码路径选择
int warpSize
- 含义:线程束大小(线程数)
- 硬件参数:SIMD宽度,通常为32
- 功能:GPU调度和执行的基本单位
- 应用场景:线程组织优化、分支 divergence 避免
int multiProcessorCount
- 含义:流多处理器(SM)数量
- 硬件参数:GPU中的计算单元数量
- 功能:决定并行计算能力
- 应用场景:性能估算、工作负载分配
2.1.3. 内存系统参数
size_t sharedMemPerBlock
- 含义:每个线程块可用的共享内存大小(字节)
- 硬件参数:每个SM上的高速可编程缓存
- 功能:线程块内线程间数据共享和通信
- 应用场景:数据重用优化、矩阵乘法、卷积运算
size_t sharedMemPerMultiprocessor
- 含义:每个多处理器的共享内存大小(字节)
- 硬件参数:SM上的共享内存总量
- 功能:限制同时驻留的线程块数量
- 应用场景:资源分配优化
size_t totalConstMem
- 含义:设备常量内存总大小(字节)
- 硬件参数:只读缓存内存
- 功能:存储只读数据,提供高速访问
- 应用场景:存储常数参数、查询表
int l2CacheSize
- 含义:L2缓存大小(字节)
- 硬件参数:全局共享缓存
- 功能:减少全局内存访问延迟
- 应用场景:内存访问模式优化
int memoryBusWidth
- 含义:全局内存总线宽度(位)
- 硬件参数:内存接口宽度
- 功能:决定内存带宽的理论上限
- 应用场景:带宽计算、性能瓶颈分析
2.1.4. 线程和块配置参数
int maxThreadsPerBlock
- 含义:每个块的最大线程数
- 硬件参数:单个线程块的大小限制
- 功能:限制线程块的规模
- 应用场景:线程块大小优化
int maxThreadsDim[3]
- 含义:每个维度线程数的最大值 [x, y, z]
- 硬件参数:线程块维度的硬件限制
- 功能:定义线程块的最大形状
- 应用场景:多维线程组织
int maxGridSize[3]
- 含义:每个维度网格大小的最大值 [x, y, z]
- 硬件参数:网格维度的硬件限制
- 功能:定义网格的最大规模
- 应用场景:大规模并行计算
int maxThreadsPerMultiProcessor
- 含义:每个多处理器的最大驻留线程数
- 硬件参数:SM的线程容量
- 功能:限制SM上同时执行的线程数量
- 应用场景: occupancy 计算
int maxBlocksPerMultiProcessor
- 含义:每个多处理器的最大驻留块数
- 硬件参数:SM的块容量
- 功能:限制SM上同时驻留的线程块数量
- 应用场景: occupancy 优化
2.1.5. 寄存器资源
int regsPerBlock
- 含义:每个块可用的32位寄存器数量
- 硬件参数:每个线程块的寄存器资源
- 功能:存储线程局部变量,提供最快访问速度
- 应用场景:寄存器使用优化
int regsPerMultiprocessor
- 含义:每个多处理器的32位寄存器总数
- 硬件参数:SM的寄存器总容量
- 功能:限制SM上所有线程的寄存器使用总量
- 应用场景:资源分配规划
2.1.6. 纹理和表面内存
各种 maxTexture* 和 maxSurface* 字段
- 含义:各种纹理和表面内存的最大尺寸限制
- 硬件参数:纹理和表面内存单元的硬件限制
- 功能:定义可用的纹理和表面内存资源
- 应用场景:图形处理、图像处理、特殊内存访问模式
2.1.7. 特性支持标志
int unifiedAddressing
- 含义:设备支持统一地址空间
- 硬件参数:UVA(Unified Virtual Addressing)支持
- 功能:CPU和GPU共享统一的地址空间
- 应用场景:简化内存管理、零拷贝内存
int managedMemory
- 含义:设备支持托管内存
- 硬件参数:UM(Unified Memory)支持
- 功能:自动内存迁移和一致性管理
- 应用场景:简化编程模型、处理大数据集
int concurrentKernels
- 含义:设备支持并发内核执行
- 硬件参数:多个内核同时执行能力
- 功能:提高GPU利用率
- 应用场景:流水线执行、多任务处理
int ECCEnabled
- 含义:ECC内存支持是否启用
- 硬件参数:错误检查和纠正功能状态
- 功能:提高内存可靠性
- 应用场景:科学计算、关键任务应用
2.1.8. PCIe和系统集成
int pciBusID, pciDeviceID, pciDomainID
- 含义:PCI总线信息
- 硬件参数:设备在PCI总线中的位置
- 功能:设备识别和选择
- 应用场景:多GPU系统管理、PCIe拓扑分析
int integrated
- 含义:设备是否为集成GPU
- 硬件参数:GPU集成方式
- 功能:区分集成和独立GPU
- 应用场景:功耗管理、性能预期
2.1.9. 高级功能支持
int cooperativeLaunch
- 含义:支持协作组启动
- 硬件参数:网格同步功能支持
- 功能:实现网格级别的同步和通信
- 应用场景:复杂并行算法
int streamPrioritiesSupported
- 含义:支持流优先级
- 硬件参数:流调度优先级支持
- 功能:控制内核执行顺序
- 应用场景:实时调度、QoS管理
2.2. cudaDeviceAttr枚举详解
cudaDeviceAttr枚举提供了通过cudaDeviceGetAttribute函数查询设备属性的标准化方式。下面我将详细解释每个枚举值的含义、功能及其与cudaDeviceProp结构体的对应关系。
2.2.1. 基本计算能力参数
| 枚举值 | 含义 | 对应cudaDeviceProp字段 | 功能描述 |
|---|---|---|---|
cudaDevAttrComputeCapabilityMajor | 主计算能力版本 | major | GPU架构的主版本号 |
cudaDevAttrComputeCapabilityMinor | 次计算能力版本 | minor | GPU架构的次版本号 |
cudaDevAttrWarpSize | 线程束大小 | warpSize | SIMD宽度,通常为32线程 |
2.2.2. 线程和块配置限制
| 枚举值 | 含义 | 对应cudaDeviceProp字段 | 功能描述 |
|---|---|---|---|
cudaDevAttrMaxThreadsPerBlock | 每块最大线程数 | maxThreadsPerBlock | 单个线程块的最大线程数量 |
cudaDevAttrMaxBlockDimX | 块维度X最大值 | maxThreadsDim[0] | 线程块X维度的最大大小 |
cudaDevAttrMaxBlockDimY | 块维度Y最大值 | maxThreadsDim[1] | 线程块Y维度的最大大小 |
cudaDevAttrMaxBlockDimZ | 块维度Z最大值 | maxThreadsDim[2] | 线程块Z维度的最大大小 |
cudaDevAttrMaxGridDimX | 网格维度X最大值 | maxGridSize[0] | 网格X维度的最大大小 |
cudaDevAttrMaxGridDimY | 网格维度Y最大值 | maxGridSize[1] | 网格Y维度的最大大小 |
cudaDevAttrMaxGridDimZ | 网格维度Z最大值 | maxGridSize[2] | 网格Z维度的最大大小 |
2.2.3. 内存系统参数
| 枚举值 | 含义 | 对应cudaDeviceProp字段 | 功能描述 |
|---|---|---|---|
cudaDevAttrMaxSharedMemoryPerBlock | 每块共享内存 | sharedMemPerBlock | 每个线程块可用的共享内存大小 |
cudaDevAttrTotalConstantMemory | 常量内存总量 | totalConstMem | 设备常量内存总大小 |
cudaDevAttrMaxSharedMemoryPerMultiprocessor | 每SM共享内存 | sharedMemPerMultiprocessor | 每个多处理器的共享内存总量 |
cudaDevAttrMaxRegistersPerBlock | 每块寄存器数 | regsPerBlock | 每个线程块可用的寄存器数量 |
cudaDevAttrMaxRegistersPerMultiprocessor | 每SM寄存器数 | regsPerMultiprocessor | 每个多处理器的寄存器总量 |
cudaDevAttrL2CacheSize | L2缓存大小 | l2CacheSize | L2缓存容量(字节) |
cudaDevAttrGlobalMemoryBusWidth | 内存总线宽度 | memoryBusWidth | 全局内存总线宽度(位) |
2.2.4. 时钟和性能参数
| 枚举值 | 含义 | 对应cudaDeviceProp字段 | 功能描述 |
|---|---|---|---|
cudaDevAttrClockRate | 核心时钟频率 | 无直接对应 | GPU核心时钟频率(kHz) |
cudaDevAttrMemoryClockRate | 内存时钟频率 | 无直接对应 | 内存时钟频率(kHz) |
cudaDevAttrSingleToDoublePrecisionPerfRatio | 单双精度性能比 | 无 | 单精度与双精度浮点性能比率 |
2.2.5. 多处理器相关参数
| 枚举值 | 含义 | 对应cudaDeviceProp字段 | 功能描述 |
|---|---|---|---|
cudaDevAttrMultiProcessorCount | 多处理器数量 | multiProcessorCount | 流多处理器(SM)的数量 |
cudaDevAttrMaxThreadsPerMultiProcessor | 每SM最大线程数 | maxThreadsPerMultiProcessor | 每个SM支持的最大线程数 |
cudaDevAttrMaxBlocksPerMultiprocessor | 每SM最大块数 | maxBlocksPerMultiProcessor | 每个SM支持的最大块数 |
2.2.6. 纹理和表面内存限制
纹理维度限制:
cudaDevAttrMaxTexture1DWidth- 最大1D纹理宽度cudaDevAttrMaxTexture2DWidth- 最大2D纹理宽度cudaDevAttrMaxTexture2DHeight- 最大2D纹理高度cudaDevAttrMaxTexture3DWidth- 最大3D纹理宽度- 等等(对应
cudaDeviceProp中的各种maxTexture*字段)
表面内存限制:
cudaDevAttrMaxSurface1DWidth- 最大1D表面宽度cudaDevAttrMaxSurface2DWidth- 最大2D表面宽度- 等等(对应
cudaDeviceProp中的各种maxSurface*字段)
2.2.7. 特性支持标志
| 枚举值 | 含义 | 对应cudaDeviceProp字段 | 功能描述 |
|---|---|---|---|
cudaDevAttrConcurrentKernels | 并发内核支持 | concurrentKernels | 是否支持并发内核执行 |
cudaDevAttrEccEnabled | ECC支持状态 | ECCEnabled | ECC内存是否启用 |
cudaDevAttrUnifiedAddressing | 统一寻址支持 | unifiedAddressing | 是否支持统一地址空间 |
cudaDevAttrManagedMemory | 托管内存支持 | managedMemory | 是否支持托管内存 |
cudaDevAttrComputePreemptionSupported | 计算抢占支持 | computePreemptionSupported | 是否支持计算抢占 |
cudaDevAttrCooperativeLaunch | 协作启动支持 | cooperativeLaunch | 是否支持协作内核启动 |
2.2.8. PCIe和系统集成
| 枚举值 | 含义 | 对应cudaDeviceProp字段 | 功能描述 |
|---|---|---|---|
cudaDevAttrPciBusId | PCI总线ID | pciBusID | PCI总线标识符 |
cudaDevAttrPciDeviceId | PCI设备ID | pciDeviceID | PCI设备标识符 |
cudaDevAttrPciDomainId | PCI域ID | pciDomainID | PCI域标识符 |
cudaDevAttrIntegrated | 集成GPU标志 | integrated | 是否为集成GPU |
2.2.9. 高级功能支持
| 枚举值 | 含义 | 功能描述 |
|---|---|---|
cudaDevAttrStreamPrioritiesSupported | 流优先级支持 | 是否支持流优先级 |
cudaDevAttrGlobalL1CacheSupported | 全局L1缓存支持 | 是否支持在L1中缓存全局变量 |
cudaDevAttrLocalL1CacheSupported | 局部L1缓存支持 | 是否支持在L1中缓存局部变量 |
cudaDevAttrPageableMemoryAccess | 可分页内存访问 | 是否支持直接访问可分页内存 |
2.2.10. 现代特性支持(较新架构)
| 枚举值 | 含义 | 功能描述 |
|---|---|---|
cudaDevAttrMemoryPoolsSupported | 内存池支持 | 是否支持异步内存分配API |
cudaDevAttrGPUDirectRDMASupported | GPUDirect RDMA支持 | 是否支持GPUDirect RDMA |
cudaDevAttrClusterLaunch | 集群启动支持 | 是否支持集群启动 |
cudaDevAttrNumaConfig | NUMA配置 | NUMA配置信息 |
cudaDevAttrNumaId | NUMA节点ID | GPU内存的NUMA节点ID |