☰
gpu_burn实战:Linux GPU稳定性压测与问题排查
2026/10/6 13:56:14 网站建设 项目流程

简介:面向 Linux/Ubuntu/CentOS 环境的 GPU 极限压力测试资源,通过长时间高负载浮点运算考察显卡稳定性与极限性能,可用于跑分对比、散热验证、驱动排错等场景,适合硬件爱好者、开发者和系统管理员使用。压缩包共 8 个文件,大小约 65KB,内含 Makefile 构建脚本、gpu_burn-drv.cpp 驱动测试源码、compare.cu 与 compare.ptx 对比测试代码、gpu_burn 可执行文件及说明.txt,结构紧凑,便于直接编译运行,阅读源码也有助于理解 CUDA 压力测试的实现思路。工具通过持续占满 GPU 计算单元,量化浮点运算能力、纹理填充率等性能指标并生成跑分报告,测试时配合温度、功耗监控,还能帮助定位散热不佳、供电不足或驱动配置异常等隐患。已有 9007 人学习下载,特别适合需要评估显卡性能、验证 Linux 环境下 GPU 稳定性的用户。

1. 先说结论:为什么 gpu_burn 适合做 Linux 下的 GPU 压力测试

在 Linux 服务器上做 GPU 性能压力测试,我这两年用得最多的就是 gpu_burn。它没有图形界面,没有排行榜,跑起来屏幕上只有一行行 Gflops 数字,却能在高负载下把供电、散热、驱动稳定性这些“看不见的问题”全逼出来。买二手卡怕翻车、机房上架前想验卡、刚换完硅脂想确认散热有没有改善,都适合先跑一遍 gpu_burn。它解决的核心问题不是“这张卡跑分多高”,而是“这张卡满载之后到底稳不稳”。

2. 环境准备与编译:驱动、CUDA、gcc 三方对齐才能编过

2.1 前置条件:先确认这三样东西版本匹配

gpu_burn 是一个用 CUDA 写的小工具,编译它不需要装完整 SDK,但 nvcc 编译器、CUDA runtime 库和显卡驱动这三样必须在场。很多人在这一步就栽了:驱动装好了,nvidia-smi能正常输出,但一编译就报找不到cuda_runtime.h,这就是典型的装了驱动却没装 CUDA Toolkit。

实际动手前我会先跑一遍下面这组命令,确认环境状态:

nvidia-smi # 查看驱动是否工作、有几张卡 nvcc --version # 确认 CUDA Toolkit 的 nvcc 编译器在 PATH 里 ls /usr/local/cuda/lib64/libcudart.so # 确认 CUDA runtime 库真实存在 gcc --version # 确认 host 编译器版本

这四条命令缺一不可。nvcc --version没有输出,说明 CUDA Toolkit 没装上或者 PATH 没配好,后面编译必挂;libcudart.so找不到,说明 CUDA 库路径没被 Makefile 搜到;gcc --version版本太新,则可能出现 nvcc 不认 gcc 的情况。我一般会把 PATH 显式指到 CUDA 目录下,避免系统装了多套 CUDA 时串台:

export CUDA_HOME=/usr/local/cuda export PATH="$CUDA_HOME/bin:$PATH" export LD_LIBRARY_PATH="$CUDA_HOME/lib64:$LD_LIBRARY_PATH"

CUDA_HOME是给 Makefile 用的搜索根目录,LD_LIBRARY_PATH是让程序运行时能找到libcudart.so。注意 Linux 下用冒号分隔路径,Windows 才是分号,这个写错会导致后面所有依赖库找不到。

2.2 源码编译:clone 下来直接 make,失败时看这一节

环境确认没问题后,编译本身很简单。把仓库 clone 到服务器任意目录,进入目录直接make:

git clone https://github.com/wilicc/gpu-burn cd gpu-burn make

make会调用 nvcc 把核心计算 kernel 编成二进制,生成的可执行文件名就是gpu_burn。这里有个细节很多人没注意:gpu_burn 的编译过程会按当前机器的 GPU 计算能力自动挑编译参数,所以 A100 和 RTX 4090 编出来的二进制不是同一套代码路径。如果你在旧机器上编完,再把二进制拷到新卡上跑,很可能会直接启动失败。

编译如果报错,绝大多数集中在两个位置。一是找不到 CUDA 头文件,二是 nvcc 不认当前 gcc 版本。前者回头检查 2.1 的路径配置;后者常见于 GCC 12/13 这类很新的版本,nvcc 对 host 编译器有版本上限,编译时直接抛unsupported GNU version!。常见做法是给 nvcc 指定一个旧一点的 gcc,或者用CUDAHOSTCXX环境变量切换:

export CUDAHOSTCXX=g++-10 make clean make

CUDAHOSTCXX是 nvcc 识别 host 编译器的环境变量,改成系统里存在的旧版本 g++ 即可。如果系统里没装旧版 gcc,另一条路是改 Makefile,在 nvcc 参数里手动加-gencode arch=compute_86,code=sm_86这类指定计算能力的选项,绕过自动探测失败的问题。具体数字要按你的卡来填,用nvidia-smi --query-gpu=name,compute_cap --format=csv就能查到。

2.3 单卡与多卡:用 CUDA_VISIBLE_DEVICES 精确控制压测对象

服务器上插多张卡是常态。gpu_burn 默认会把当前对 CUDA 可见的所有 GPU 全部拉起来烧机,但生产环境里你往往只想测其中一张,或者想单独压某张刚返修的卡。

控制可见卡范围靠环境变量,不需要改代码:

export CUDA_VISIBLE_DEVICES=0,2 ./gpu_burn 60

这里的0,2是指卡的编号,不是系统里的 PCIe 槽位号。编号顺序可以用nvidia-smi -L确认。跑起来之后,屏幕上会同时出现两张卡各自的 Gflops 行。要注意的是,CUDA_VISIBLE_DEVICES 一旦设置,对系统里所有 CUDA 程序生效,不只是 gpu_burn,所以在跑别的任务前记得unset CUDA_VISIBLE_DEVICES。

多卡并行时还有一个环境变量值得提:GPU_BURN_MAX_PROCESSES控制每张卡最多起多少个压测进程,默认是一张卡一个进程。通常不需要动它,但如果你在调其他 CUDA 进程共存时的稳定性,可以把它设成 2 或 3,模拟多进程抢占 GPU 的情况。

3. 跑起来:参数怎么设,输出怎么读

3.1 压测时长与环境变量:别用默认值,显式传秒数

gpu_burn 的用法很直白,第一参数就是压测秒数:

./gpu_burn 3600

这条命令会在满负载下持续跑 3600 秒。如果你不传参数,它会快速跑一小段就结束,那种模式只能验证程序能不能启动,不能当稳定性测试用。我一般把压测时长分成三档:临时验机 300 秒,常规验收 3600 秒,出现断续故障的设备跑 7200 秒以上过夜测。

gpu_burn 还支持用环境变量替代命令行参数,适合写进脚本统一管理。整理成一张速查表:

环境变量作用示例
GPU_BURN_TIME压测总时长,单位秒export GPU_BURN_TIME=3600
GPU_BURN_DISPLAY_INTERVAL刷新间隔,单位秒export GPU_BURN_DISPLAY_INTERVAL=10
CUDA_VISIBLE_DEVICES指定压测哪些 GPU 编号export CUDA_VISIBLE_DEVICES=1
GPU_BURN_MAX_PROCESSES每张卡压测进程数export GPU_BURN_MAX_PROCESSES=2

我实际跑的时候习惯把日志同时落盘,防止终端滚动把中间结果冲掉:

./gpu_burn 3600 | tee gpu_burn_$(date +%Y%m%d_%H%M%S).log

tee会把 gpu_burn 的屏幕输出原样写进日志文件,文件名带时间戳,方便多次压测后按批次归档。这里注意别用>直接重定向,否则你在终端上完全看不到实时进度,万一中途卡死很难判断是程序死了还是在跑。

3.2 Gflops 跑分到底怎么读:别把它当显卡天梯分

gpu_burn 输出最核心的一列就是 Gflops,单卡会显示类似GPU 0: 771.2 Gflops这样的行,每隔几秒刷新一次。第一次用的人容易误读这里,以为它是 Benchmark 跑分,要和别人机器上的数字对比高低。

实际上,这个数字的意义主要在两处。第一,它证明 GPU 计算单元此时处于满载状态,没有因为驱动问题或占用冲突而偷偷降速;第二,它的稳定性比绝对值更重要——同一张卡持续压测一小时,Gflops 应该稳定在一个窄区间内波动,如果曲线一路向下掉,说明芯片散热有问题,或者供电在持续衰减。

我一般在压测时会顺手记录启动阶段和稳定阶段两组数据。比如开机冷态时第一次刷 Gflops 是 780,跑到 20 分钟后稳定在 745 左右,这是正常的热降频曲线;但如果从 780 直接掉到 400 以下,那基本可以判定卡有热管理问题,压测完直接进检修流程。横向和其他卡比也没有意义,同一张卡在不同驱动版本、不同功耗墙设置下能差出 10% 以上。

3.3 联动 nvidia-smi:温度、功耗和频率一起看才有效

gpu_burn 本身只报告算力,温度和功耗它不管。完整的一次压测,必须同时开一个 nvidia-smi 监控窗口,把温度、功耗、SM 频率实时打出来:

nvidia-smi --query-gpu=index,temperature.gpu,power.draw,clocks.sm,utilization.gpu \ --format=csv -l 5

参数含义分别是卡编号、GPU 温度、当前功耗、SM 频率、利用率。-l 5表示每 5 秒刷新一次。压测过程中这张表应该满足三个条件:利用率稳定在 99% 或 100%;功耗接近此卡的 TGP 上限;温度持续爬升后稳定在某个平台期,不再无限上涨。

这三个条件缺一不可。如果利用率不满,说明计算任务没有真正压满 GPU,大概率是被图形界面或别的 CUDA 进程抢了资源;如果功耗一直上不去但温度正常,可能是卡被锁频了;如果温度完全失控直线飙升,那就是散热系统的问题。我都是开两个终端,左边跑 gpu_burn,右边跑这个监控,这样任何异常都能第一时间对到时间点。想要更高精度的记录,把-l 5改成-l 1,每秒采样一次,代价是终端滚动很快,日志文件也会大不少。

4. 避坑清单:编译失败、跑不满、静默掉驱动的四处实战排查

4.1 现象:make 时报 unsupported GNU version,装上旧版 gcc 也编不过

有次在一台新到货的机器上编译,环境是全新的,驱动、CUDA 都正常,但make一跑就报unsupported GNU version! GCC 13.2.0。原因是这台机器操作系统镜像自带 GCC 13,而这张卡对应的 CUDA 版本只支持到 GCC 12。我当时的解决方法是装 g++-10 后设置CUDAHOSTCXX,重新make clean && make一次通过。这里有一条血泪经验:改完编译器版本后一定要make clean,否则之前编译出的临时对象文件残留,会让你误以为还是老问题。另外,解掉这个坑只是开始,编完的二进制最好在当前机器上先跑 30 秒验证能启动,再拿去别处用。

4.2 现象:跑压测时 Gflops 数值难看,温度也始终上不去,像在偷懒

有次在桌面版 Ubuntu 上给一张 3090 做验收,gpu_burn 跑起来 Gflops 只有正常值的六成,温度在 50 度就不涨了。后来排查发现是 Xorg 桌面环境占用了 GPU 做渲染,CUDA 拿到的是被分走的计算资源,并没有独占整卡。解决方法是把机器切到纯命令行模式再跑,或者至少把图形会话停止掉。这条对服务器用户影响不大,但对带显示接口的工作站很常见。如果你在图形界面里压测发现 Gflops 异常,先别怀疑卡坏,nvidia-smi里看一眼利用率是不是被Xorg进程占掉了一部分,再决定要不要切换运行级别。

4.3 现象:四卡机器只输出了两张卡的 Gflops,另外两张没动静

多卡服务器上最容易踩的坑是编号认知错位。有次我在八卡机器上压测,只跑了四张卡,一开始以为另有四张卡故障了,后来nvidia-smi -L一看,另外四张卡被之前某次任务设置过CUDA_VISIBLE_DEVICES的残留环境变量屏蔽了。环境变量是继承进 shell 的,新开的终端窗口如果沿用了旧配置,CUDA 程序就只能看到名单里的卡。解决方式是检查当前 shell 里有没有CUDA_VISIBLE_DEVICES残留,确认后用unset清掉再跑。更严谨的做法是在压测脚本里显式声明export CUDA_VISIBLE_DEVICES=0,1,2,3,写明你要压哪些卡,而不是依赖默认行为,这样日志里也有据可查。

4.4 现象:压测中途没有任何报错,进程直接消失,终端回到提示符

这是最让人头疼的翻车——gpu_burn 不是诊断工具,它不保证在出错时给你一个红色的报错码。进程突然消失,往往意味着 CUDA 驱动层面的异常已经触发系统把进程杀了,或者显卡掉驱动后计算上下文被重置。我的处理习惯是压测结束后立刻查两样东西:dmesg -T | grep -i nvrm看内核日志里有没有 NVRM 错误,以及nvidia-smi是否还能正常列出所有卡。如果 dmesg 里有 NVML/NVRM 报错,基本可以确认是驱动或供电问题。还有一次类似情况出在电源线没插紧上,机器四卡满负载时 PCIe 供电不稳,进程随机消失,换线后问题消失。这类故障不会稳定复现,所以压测日志和内核日志一定要保留现场,别跑完就删。

5. 再进一步:把压测封装成一套带记录和判定的脚本

跑过几次手工压测后,我把它固化成了一个脚本。工作逻辑很简单:后台用 nvidia-smi 每 5 秒记录一次温度和功耗,前台跑 gpu_burn 完整压测,结束后脚本根据进程退出状态和日志大小给出 PASS 或 FAIL 结论。

#!/usr/bin/env bash set -uo pipefail OUT_DIR="${1:-./gpu-burn-results}" mkdir -p "$OUT_DIR" LOG="$OUT_DIR/$(date +%Y%m%d_%H%M%S).log" MON="$OUT_DIR/$(date +%Y%m%d_%H%M%S)_mon.csv" nvidia-smi --query-gpu=index,temperature.gpu,power.draw,clocks.sm,utilization.gpu \ --format=csv,noheader -l 5 >> "$MON" & MON_PID=$! ./gpu_burn "${GPU_BURN_TIME:-3600}" > "$LOG" 2>&1 BURN_RET=$? kill "$MON_PID" 2>/dev/null || true if [ "$BURN_RET" -eq 0 ] && [ -s "$LOG" ]; then echo "PASS: gpu_burn 完整跑完指定时长" awk -F, 'NR>1{ if($2>mt) mt=$2; if($3>mp) mp=$3 } END{ printf "max_temp=%s, max_power=%s\n", mt, mp }' "$MON" else echo "FAIL: 日志见 $LOG, 查 dmesg" exit 1 fi

脚本里nvidia-smi的 CSV 输出写进_mon.csv,awk最后统计出压测期间出现的最高温度和最高功耗。BURN_RET拿到的是 gpu_burn 自身的退出码,如果进程是正常跑满时长退出的,退出码为 0,再配合日志非空验证,就能判定这次压测没有发生中途消失的静默崩溃。从那以后我每次验收新卡,都强制走一遍这个流程,先短跑 300 秒确认基本盘,再根据情况加大到 3600 秒过夜烧。过程里不再盯着终端看,只看脚本最后的 PASS 和两个数值,省心也省得误判。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询