状态:实测(2026-10-31)。 在一台 24GB GPU 服务器上应用了 gpu-unlock 2.0.0,并在应用前后使用相同的临时 Pod 和相同的脚本进行了测量。矩阵乘法是每个数据类型重复 7 次、性能分析重复 3 次的中位数,延迟是运行多次 600 帧会话得到的值。编写规则:以实测数据为基础,无法测量的标记为“未实测”,未能确认原因的解释标记为“推测”。本文不鼓励使用。
目录
- 1. 从结论说起
- 2. gpu-unlock 的作用
- 3. 应用前需要了解的风险与许可证
- 4. 测量环境与方法
- 5. 应用前的上限分析:Tensor Core 占比 4.7%
- 6. 是否解除了限制:矩阵乘法达到 1.61 倍,为何不是 2 倍
- 7. 输出是否相同:对照组与按位比较
- 8. 实时记分牌:上限之内的 −0.9%
- 9. 端到端延迟从 22.5 降至 17.4 ms 并非 gpu-unlock 的效果
- 10. 还原方法
- 11. 总结
1. 从结论说起
我们亲自验证了“消费级 GPU 的 Tensor Core 被限制在半速,解除限制后可以翻倍”这一说法。结果证明对了一半,另一半则取决于具体情况。
- 限制确实被解除了。 内核日志中记录了
gpu_unlock: unlocked,速度选择寄存器 SS0 从0x43301046变为了0x88888888。矩阵乘法 8192³(FP32 累加)的 BF16 为 70.1 → 113.0 TFLOPS(×1.61),FP16 为 68.4 → 108.9,TF32 为 37.2 → 61.3。不使用 Tensor Core 的 FP32 保持 23.8 → 23.8 不变(对照组)。 - 没能达到 2 倍而是 1.6 倍,是因为功率原因。 每时钟吞吐量增加了约 1.95 倍,但当显卡触及 350W 上限时,SM 时钟频率从约 1710 MHz 下降到了 1395 MHz。应用后的时钟频率是以 100 ms 为间隔采样的,而应用前的时钟频率是以 0.5 秒间隔的样本进行近似测量的。
- 输出是相同的。 我们在确定性设置下对比了生产实时模型的 6 种输出各 200 帧,sha256 完全一致。不过,在与生产环境相同的设置(
cudnn.benchmark=True)下,解除限制后 cuDNN 选择了不同的卷积算法,因此该设置下的按位一致性属于未实测。 - 实时乒乓球记分牌的找球模型提速了 0.9%。 每帧 GPU 内核时间从 9.09 减少到 9.00 ms。落在了应用前通过性能分析预先计算出的上限 −2.3% 以内。这是因为该模型的 GPU 时间中 Tensor Core 仅占 4.7%。
- 端到端延迟从 22.5 降至 17.4 ms 并非 gpu-unlock 的效果。 GPU 侧和工作线程路径保持不变,在同一次启动中重新测量时,26.2 ms 和 17.2 ms 交替出现。这是服务器侧 CPU 部分的差异,其原因最终未能确定(第 9 节)。
2. gpu-unlock 的作用
Tensor Core 是一种专用的计算单元,可以一次性处理小型矩阵乘法。NVIDIA 的消费级显卡将以 FP32 累加输入的 FP16、BF16 和 TF32 的 Tensor Core 运算速度,运行在采用相同芯片的专业级显卡的一半速度。训练和未量化的推理大多走这条路径。以 FP16 累加的运算、INT8 以及不使用 Tensor Core 的 FP32 与此限制无关。
gpu-unlock 是一个在引导时修改决定此速度的寄存器的 Linux 内核模块。总结仓库 README 中的“How it works”和“Boot flow and opt-in”两节如下:
- 软件包将模块和固件放入 initramfs 中。因此,模块在 NVIDIA 驱动程序接管显卡之 前 运行。
- 仅当内核命令行中包含
gpu_unlock.targets=时,模块才会工作。其中写入了all或 PCI 地址。 - 模块通过从 NVIDIA 驱动程序包中提取的签名引导固件(由 GPU 安全处理器运行的 booter)获得写入受保护寄存器的权限,并将速度选择寄存器 SS0 写入
0x88888888,SS1 写入0x8。 - 在重置显卡(FLR)后放弃控制权。随后, 未修改的 NVIDIA 驱动程序像往常一样接管显卡。
由于该方式既不修改驱动程序也不重新烧录 VBIOS,因此仓库说明中指出升级驱动后无需再次操作。如果在启动完成后手动加载模块,则对于驱动程序已经接管的显卡不会产生任何作用。
应用后的服务器内核日志如下(仅保留必要部分,地址已缩短):
gpu_unlock: loading out-of-tree module taints kernel.
gpu_unlock: module verification failed: signature and/or required key missing - tainting kernel
gpu_unlock: stage=gfw plm=0xffffff8f ss0=0x43301046 ss1=0x6 ...
gpu_unlock: pass=1/2 attempt=1 ... ret=0
gpu_unlock: pass=2/2 attempt=1 ... ret=0
gpu_unlock: stage=host ss0=0x88888888 ss1=0x8 ...
gpu_unlock: stage=flr ... ss0=0x88888888 ss1=0x8 ...
gpu_unlock: unlocked
所有步骤都在同一秒内完成。应用后,驱动程序版本(580.95.05)、最高时钟频率(2100 MHz)和功率上限(350W)均保持不变。
3. 应用前需要了解的风险与许可证
该模块是触及 GPU 安全处理器启动路径的 第三方 代码。并非由 NVIDIA 制作或支持。以下是仓库文档以及本次应用中的实际观察:
| 项目 | 内容 | 依据 |
|---|---|---|
| 内核 taint | 由于是树外模块,内核打上了 O(树外)标记,并且由于 DKMS 使用自带密钥签名但该密钥未注册导致验证失败,还打上了 E(无签名)标记。 /proc/sys/kernel/tainted 是 12289(P·O·E 的总和)。内核开发者可能不接受带有 taint 的内核的错误报告 |
实测(内核日志) |
| Secure Boot | 此服务器关闭了 Secure Boot,应用脚本在开启时会中止。若要在开启状态下使用,必须对模块进行签名并将该密钥注册到固件中,但本次未作尝试 | 实测(应用脚本),签名路径未实测 |
| 支持范围 | 文档记载 Ampere 代稳定,Ada 和 Turing 代处于实验阶段,Blackwell 不支持 | 仓库 README |
| 笔记本显卡 | 当独立 GPU 处于休眠状态且完全断电时,解除状态会悄然消失。仓库也指出结果会混杂。仅将其作为实验处理是正确的 | 仓库 README,未实测 |
| 节能 | 从内存节能(suspend to RAM)恢复时会重新解除。休眠(hibernation)未作处理 | 仓库 README,未实测 |
| 失败时 | 如果显卡固件没有停止,模块会将 DMA 缓冲区一直把持到下一次断电。若要重试,需完全关闭电源 | 仓库 README,未实测 |
| 屏幕 | 如果是输出画面的显卡,从重置到驱动接管期间屏幕会保持空白 | 仓库 README,本次服务器无画面运行 |
| 发热与寿命 | 仓库 FAQ 记载造成损害的可能性较低。本次连续运行 8 秒矩阵乘法期间,功率未超过上限(350W),最高温度为 67°C | 仅实测短期数值,长期影响未实测 |
许可证。 内核模块和打包采用 GPL-2.0-only。但是,模块使用的固件是从 NVIDIA 驱动程序包(610.43.03)中按字节原样提取的, NVIDIA 固件遵循 NVIDIA 的许可证(驱动程序最终用户许可协议)。 仓库的 firmware/NOTICE.md 声明,公开的开源内核模块源代码的许可证不适用于此固件,并且不主张再分发权限,其主要目标是允许个人在自己的设备上打包。因此,每次构建都会直接从 download.nvidia.com 下载驱动程序 .run(344,190,507 B)和内核模块源代码(26,172,192 B),并在现场提取固件。本次应用也是仅在服务器内部这样构建的,并未将构建出的固件或软件包分发给任何人。本文并非法律意见。若要在商业环境或多台设备上部署,请务必先阅读 NVIDIA 协议原件。
重启改变的不仅是 gpu-unlock。 update-grub 由于一并应用了几个月前修复但未反映的 /etc/default/grub 编辑,导致内核命令行中漏掉了 quiet splash swapaccount=0 vt.handoff=7 ,并且 IOMMU 参数被输入了两次。这相当于前后对比多了一个变量,如果在并排查看重启前后的 /proc/cmdline 之前是不会发现的。建议在应用前先确认 update-grub 将生成什么。
4. 测量环境与方法
| 项目 | 值 |
|---|---|
| GPU | Ampere 代(GA102)24GB 消费级显卡,功率上限 350W(设置最大值也为 350W),驱动程序 580.95.05 |
| 服务器 | 混合(P核与E核)24线程桌面 CPU,Ubuntu 25.04,内核 6.14.0-37-generic |
| gpu-unlock | 2.0.0,提交 7eb51bc,DKMS 软件包,目标为该显卡的单个 PCI 地址 |
| 测量 Pod | 与生产记分牌工作线程相同的镜像(PyTorch 2.9.1+cu128,cuDNN 9.10)及相同的权重(只读),GPU 时间切片一片,CPU 4 与内存 8Gi 限制,运行结束后销毁的临时 Pod |
| 负载 | 测量期间生产记分牌会话和批处理任务为 0 个 |
测量分为四项。在应用前后使用相同的 Pod 和相同的脚本运行。
- 矩阵乘法。
torch.mm使用nvidia-smi连续运行 8192³ 和 4096³ 每次 20 次(4096 为 100 次)的 7 个窗口的中位数。关闭了 FP16 和 BF16 的降精度累加,仅测量 FP32 累加。时钟频率和功率是同一时间段的采样(应用前 0.5 秒,应用后分别连续运行 8 秒并以 100 ms 采样)。 - 内核性能分析。
torch.profiler的 trace 中,将 Tensor Core 矩阵乘法、卷积(s1688gemm,xmma,tensorop)与其余部分区分开来。以批大小 1、2、3 各运行 3 次寻球模型 BlurBall(HRNet 系列,1.49M 参数,单输入窗口 9×288×512)。 - 比特比较。 将相同的 200 帧输入到线上模型网络(BlurBall、EfficientTAM 视频编码器、球桌分割头、球桌顶点头)中,输出
6 种按帧的 sha256。属于确定性设置(
cudnn.benchmark=False,cudnn.deterministic=True,use_deterministic_algorithms,CUBLAS_WORKSPACE_CONFIG=:4096:8),精度与线上相同。应用前运行了两次,首先确认两者是否一致。 - 端到端延迟。 将线上 worker 直接在 Pod 中运行,像浏览器一样以 30fps 发送 JPEG,测量「发送时刻 → 收到该帧响应的时刻」。 未收到响应的帧最多堆积 3 张,并丢弃前 2 秒。网络因素已被排除。
5. 运行前先看上限:Tensor Core 占比 4.7%
gpu-unlock 只能让 Tensor Core kernel 变快。因此,我的模型能变快多少,上限由「GPU 时间中 Tensor Core kernel 所占的份额」决定。 在运行前首先测量了这一点。
| 寻球模型(批大小 1,每帧) | 应用前实测 |
|---|---|
| GPU kernel 时间 | 9.09ms(427 个 kernel) |
| 其中 Tensor Core kernel | 0.42ms(2 个 TF32 矩阵乘法 kernel), 4.7% |
| 最大的 kernel | 批归一化(2.9ms)、clamp、加法等受内存限制的小 kernel |
| 卷积 | 尽管允许使用 TF32(cudnn.allow_tf32=True 默认值), cudnn.benchmark 仍选择了 FP32 winograd(非 Tensor Core) |
对于小分辨率和少通道(16–128)的 HRNet 来说,计算本身不贵,kernel 数量和内存往返才是开销大头。即使 Tensor Core kernel 缩减正好一半, 减少的时间也只有 0.21ms,这就是 上限 −2.3% 。如果假设「因为是 FP32 模型,所以会用 TF32 Tensor Core 运行」,那就猜错了。 即使 cuDNN 允许 TF32,它也可能根据基准测试结果选择不使用 Tensor Core 的算法,因此不能靠假设,必须统计 kernel 名称。
通过相同的测量,我们也提前观察了其他路径。如果用 BF16 autocast 运行模型(这与线上改动不同,未评估精度),kernel 时间将变为 7.67ms,Tensor Core 占比上升至 26%,上限随之增大。寻找球桌(仅在请求时运行的分割模型)在 49ms 的 GPU 时间中,Tensor Core 约占 21ms, 但墙钟时间(wall-clock time)为 1.4 秒,其中大部分是 CPU 后处理。这两个数字都提前表明了:「即使 GPU 变快了,用户感受到的时间也几乎没有变化」。
6. 解锁了吗:矩阵乘法为 1.61 倍,并非 2 倍的原因
| 8192³,FP32 累加 | 应用前(TFLOPS) | 应用后 | 倍数 |
|---|---|---|---|
| BF16 | 70.1 | 113.0 | ×1.61 |
| FP16 | 68.4 | 108.9 | ×1.59 |
| TF32 | 37.2 | 61.3 | ×1.65 |
| FP32(非 Tensor Core,对照组) | 23.75 | 23.83 | ×1.00 |
在 4096³ 下也是 BF16 ×1.68、FP16 ×1.65、TF32 ×1.65、FP32 ×1.00。由于仓库 README 收集的用户报告显示同等级显卡从 BF16 的 75 提升到 125 TFLOPS(+65%),因此处于相近的水平。
没能达到 2 倍的原因从功耗中可见一斑。在运行矩阵乘法期间, nvidia-smi 的时钟频率限制原因几乎全程都是「软件功耗上限」,
功耗最高达到 348.9W,紧贴着 350W 的上限。若除以同时段的 SM 时钟频率,结果如下。
| 8192³ | 应用前 SM 时钟 | 应用前每时钟 | 应用后 SM 时钟 | 应用后每时钟 | 每时钟倍数 |
|---|---|---|---|---|---|
| BF16 | 约 1710MHz | 41.7 TFLOPS/GHz | 1395MHz | 81.3 | ×1.95 |
| FP16 | 约 1680MHz | 41.3 | 1365MHz | 80.5 | ×1.95 |
| TF32 | 约 1815MHz | 20.7 | 1485MHz | 40.9 | ×1.98 |
| FP32 | 约 1470MHz | 16.3 | 1455MHz | 16.4 | ×1.01 |
每时钟的值是将同一区间的 TFLOPS 除以该区间 SM 时钟的中位数得到的。根据 GA102 白皮书(文档标准),FP32 累加 FP16 和 BF16 在半速下的每时钟最大值约为 41.9 TFLOPS/GHz,全速下则为其两倍。应用前的 41.7 是半速的 99%,应用后的 81.3 是全速的 97%。 由此可以解读为:每时钟性能几乎正好翻倍,由于工作量加倍导致功耗率先触顶,从而使时钟频率下降了 18%
。1.95 × (1395 / 1710) ≈ 1.59,这与测得的 1.61 相吻合。 推测。应用前的时钟频率是在 0.5 秒间隔的样本中为每个 dtype 区间读取 4–8 个值得到的近似值。有两种验证方法,
但我们都没有做(未实测)。一种是提高功耗上限,看倍数是否接近 2,但该显卡可设置的最大值为 350W,
无法再调高。另一种是使用 nvidia-smi -lgc 将 SM 时钟锁定在功耗上限之下的同一数值并前后测量。由于该服务器与线上业务共享 GPU,因此未更改时钟设置。
7. 输出是否相同:对照组与比特比较
既然有了速度变化的数字,同样也需要「其他未变」的数字。我们准备了两个方面。
- 对照组。 不使用 Tensor Core 的 FP32 矩阵乘法从 23.75 变为 23.83 TFLOPS(×1.00),关闭 TF32 的寻球模型 kernel 从 9.28 变为 9.30ms(+0.2%)。 与限制无关的路径保持不变,这也意味着其他变化(时钟、驱动、温度)并未干扰结果。
- 比特比较。 在应用前连续运行两次相同的比较,首先确认 6 种输出完全相同(即测量方法本身具备确定性)。 随后,将应用后的输出与应用前的基准进行比较。
| 输出(确定性设置) | 比较数量 | 不同数量 | 原始张量最大绝对误差 |
|---|---|---|---|
| 寻球 BlurBall | 198 | 0 | 0 |
| EfficientTAM 视频嵌入 | 200 | 0 | |
| EfficientTAM 高分辨率特征 | 200 | 0 | |
| 球桌分割低分辨率 logits | 200 | 0 | 0 |
| 球桌分割 IoU | 200 | 0 | |
| 球桌顶点热力图 | 200 | 0 | 0 |
这六项是逐帧单独比较 sha256 的结果。由于球桌查找的最终结果(经过多个模型和后处理得到的四边形)只比较了一个聚合哈希, 且未能按项统计相同数量,因此将其从「已确认」中移除。
局限性。 这种一致性仅适用于确定性设置。线上业务以 cudnn.benchmark=True 运行,并且如第 8 节所示,解锁后 cuDNN 将部分卷积替换为了
TF32 Tensor Core kernel。算法改变后,加法顺序也会发生变化,因此不能断言线上设置的输出在比特级别上完全相同。我们并未进行该项比较(未实测)。
「输出在比特级别相同」这一结论必须始终附加其适用的具体设置。
8. 实时记分板:上限之内的 −0.9%
| 寻球模型 GPU kernel(每帧,3 次中位数) | 应用前 | 应用后 | 变化 |
|---|---|---|---|
| 线上设置,批大小 1 | 9.087ms | 9.001ms | −0.9% |
| 线上设置,批大小 2 | 16.24ms | 16.00ms | −1.5% |
| 线上设置,批大小 3 | 23.28ms | 22.87ms | −1.8% |
| 关闭 TF32(对照组),批大小 1 | 9.284ms | 9.302ms | +0.2% |
| BF16 autocast,批大小 1(与线上不同的改动) | 7.666ms | 7.357ms | −4.0% |
| FP16 autocast,批大小 1(与线上不同的改动) | 7.219ms | 7.071ms | −2.0% |
批大小 1 的 −0.9% 在预先计算的 −2.3% 上限之内。从 worker 内部的解码到推理的单帧路径也呈现出相同的幅度,从 13.04 降至 12.96ms(p50)。
未能达到理论上限并不奇怪。上限基于 Tensor Core kernel 缩减正好一半的假设,而实际上 Tensor Core
kernel 时间从 0.42 增加到了 0.73ms, 有所增加。 随着解锁后 TF32 卷积变快, cudnn.benchmark 将部分卷积从 FP32 winograd 替换为了
TF32 implicit GEMM kernel,取而代之的是其余 kernel 从 8.67 缩减至 8.27ms。总计减少了 0.09ms。
Tensor Core 使用越多的路径,收益越大。批大小增大时,降幅扩大至 −1.5%、−1.8%,球桌查找的 flash attention kernel 从 6.97 降至 4.75ms(−32%),单次查找的 GPU 时间从 49.3 降至 43.1ms。即便如此,单次查找的墙钟时间仍为 1,399 至 1,412ms,没有变化。 这是因为消耗时间的并非 GPU,而是 CPU 后处理。
9. 端到端延迟从 22.5 降至 17.4ms 并非 gpu-unlock 的效果
在同一测量中,端到端延迟(单 30fps 会话,p50)从 22.5ms 降至 17.4ms,减少了 23%。单看这个表格,很容易让人想写成 gpu-unlock 将延迟降低了 5ms。然而,GPU kernel 仅减少了 0.09ms,worker 路径也只缩短了 0.08ms。剩下的 5ms 来自其他地方。我们进行了更多测量。
GPU 侧保持不变。 在会话运行期间,GPU 在前后均处于 P2 状态,SM 1695MHz,170W,利用率 29–30%。 当同时运行三个会话时,延迟保持在 26.5 至 26.3ms 不变。worker 报告的服务器内部时间(收到时刻 → 得出响应时刻)从 20.3 降至 15.9ms,因此 差异在服务器侧。通过套用测量阶段的包装器并在应用后拆分服务器内部时间,发现 GPU 推理为 11.7ms,其前的 CPU 阶段(JPEG 解码、 球桌光流跟踪、等待)为 4.2ms。由于 GPU 推理前后一致,由此可计算出应用前的 CPU 阶段约为 8.6ms。
在同一次启动内重新测量时,数值出现了波动。 在保持 gpu-unlock 的情况下,未更改图像、脚本和设置,在 20 分钟内又测量了三次。
| 测量 | gpu-unlock | 端到端 p50(按会话) | 服务器内 p50 | 服务器 CPU 使用率(总计) | 测量 Pod CPU | 同服务器的 CI 构建 |
|---|---|---|---|---|---|---|
| 应用前 | 无 | 23.6, 22.5, 22.3 | 20.3 | 7.2% | 0.90 核 | 无 |
| 应用后 | 有 | 17.4, 19.1, 17.2 | 15.9 | 7.6% | 0.76 核 | 1.46 核 |
| 复测 1 | 有 | 26.2, 26.2, 26.8 | 23.7 | 9.2% | 0.96 核 | 0.04 核 |
| 复测 2 | 有 | 17.4, 17.2, 17.0 | 15.7 | 8.5% | 0.66 核 | 0.99 核 |
| 复测 3 | 有 | 16.8–18.1(12 个会话) | 15.4–16.4 | 约 9% | 0.5–1.4 核 | 1.0–1.4 核 |
在保持 gpu-unlock 的同一次启动中,间隔 4 分钟分别出现了 26.2ms 和 17.2ms。22.5 → 17.4 正好落在这个波动范围内。因此, 通过实测可以断言这并非 gpu-unlock 的效果,而具体原因是什么则是下一步需要解决的问题。
最初提出的假设是错误的。 重启后,原本在同一台服务器上的 CI 服务器和 Web Pod 迁移到了其他服务器,因此我们猜测是「CPU 竞争减少了」。然而,在应用前测量时,这些 Pod 使用的 CPU 总和约为 0.1 核,前后服务器整体的 CPU 使用率都在 7–9% 之间。相反, 较慢的两次发生在服务器几乎没有其他任务的时候,而较快的三次发生在同一服务器上的 CI 构建正在使用 1–1.5 核 CPU 时。变慢时,测量 Pod 在相同任务上使用了更多 CPU(0.90–0.96 核对 0.66–0.76 核)。
这种形态指向了 CPU 节能方面。该服务器在 powersave 调节器中使用了最深的空闲状态(C10,退出需要 680µs),而 30fps 的一个会话在每 33ms 中工作约 16ms,其余时间休息。也就是说,当服务器整体空闲时,核心会深度休眠或降低时钟频率,从而付出每个帧被唤醒的代价。为了验证这一点,我们在同一个 Pod 内开启和关闭一个持续运行核心的进程(nice 19)并交替测量(上表中的「再次 3」),但当时由于正在进行 CI 构建,无论开闭都在 17ms 左右。我们等待了 30 分钟以期在服务器空闲时再次测量,但由于构建任务接连不断,没有等到那个时机。由于未能重现变慢的状态, 该解释仅作为推测保留。
要进行确认,需要挑选服务器空闲的时间再次进行交替测量,或者在固定核心和限制 C 状态的情况下进行测量(未实际测量)。
这件事中值得借鉴的与其说是原因本身,不如说是排查顺序。当端到端的数据变好时,不要立刻下结论,而是应该 在相同条件下重新测量以首先观察波动范围,并将其划分为部分路径(GPU 内核、工作线程路径、服务器内部阶段)来甄别具体是哪里发生了变化。这一次,由于部分路径保持不变,我们得以将 gpu-unlock 从原因中排除。
10. 回滚方法
这是记录在仓库文档和应用脚本中的方法。这次我们没有进行回滚(未执行)。
| 范围 | 方法 |
|---|---|
| 单次关闭 | 在启动画面的 GRUB 编辑中删除 gpu_unlock.targets=... 并启动 |
| 持续关闭 | /etc/default/grub 将恢复到应用前的备份,然后 sudo update-grub 并重启。即使模块仍然存在,如果没有这个参数,它也不会执行任何操作 |
| 完全卸载 | 删除软件包(Debian 系列 sudo apt-get remove gpu-unlock-dkms)。initramfs 将被重新生成 |
| 确认 | 检查本次启动的内核日志(journalctl -k -b)中是否没有 gpu_unlock: unlocked ,以及矩阵乘法 BF16 是否恢复为约 70 TFLOPS |
由于设置是在启动时写入寄存器的,因此不会残留在显卡中。完全断电后将恢复原状。
11. 总结
| 确认事项 | 原因(本文的实际测量) |
|---|---|
| 在应用前测量 GPU 时间中张量核心内核的占比 | 寻找球模型占 4.7%,因此上限为 −2.3%,实际测量值为 −0.9% |
| 按内核名称统计 | 即使允许 TF32,cuDNN 也选择了不使用张量核心的卷积 |
| 同时观察功率上限和时钟频率 | 虽然每个时钟周期约为 1.95 倍,但由于触及 350W 限制导致时钟频率下降了 18%,实际为 1.61 倍 |
| 设置对照组 | FP32 矩阵乘法(×1.00)和关闭 TF32 的模型(+0.2%)保持不变,可以认为没有受到其他变化的影响 |
| 对比二进制时附加设置 | 在确定性设置下,6 种情况完全相同,但在生产设置中,解除后算法选择发生了变化,因此未实际测量 |
| 切勿将原因直接归结于端到端的数据 | 22.5 → 17.4ms 处于同一次启动内的波动范围(17–26ms)内,且部分路径保持不变 |
| 观察重启同时改变了什么 | 积压的 GRUB 编辑一并生效,导致内核命令行发生了更多变化 |
综上所述,本模块使消费级显卡的 FP32 累加张量核心速度在每个时钟周期翻倍这一点已在该服务器上得到证实,但在功率上限下,矩阵乘法大约提升了 1.6 倍。如果工作负载的大部分时间都是大型 BF16·FP16 矩阵乘法(如语言模型的提示词处理或训练),那么速度的提升将会接近这个数值;而如果是像小型卷积模型那样受限于内存和内核数量的工作负载,则几乎不会发生变化。到底是哪种情况,在应用前进行一次性能分析便可知晓。而作为代价,我们需要承担未经签署的第三方模块干预 GPU 启动路径,并直接读取 NVIDIA 固件许可条款的风险。
TT 的一句话。 把自行车变速器调高一个档位,踩一圈就能走两倍的距离。然而腿部的力量(350W)没有变,所以脚踏板转动变慢了,最终速度只快了 1.6 倍!而且我找乒乓球的程序大部分时间都花在系鞋带上(内存往返),所以即使换了档位也几乎没有变化。如果某天你早到了学校,可不能把功劳归于变速器哦。因为那天的风说不定是从背后吹来的呢。