基于RTX 4090的fp64数组乘法性能异常问题问询
RTX 4090 FP64数组乘法性能异常解析
实验背景
为测试硬件能力,在RTX 4090上执行100万次FP64数组逐元素乘法运算,实验结果如下:
8192: t1 * t2 took 2.081 16384: t1 * t2 took 2.095 32768: t1 * t2 took 2.066 65536: t1 * t2 took 2.057 131072: t1 * t2 took 2.209 Q1: 数组规模远超CUDA核心数为何耗时仍约2秒? 262144: t1 * t2 took 2.991 524288: t1 * t2 took 5.989 耗时翻倍符合预期 1048576: t1 * t2 took 10.388 仅慢1.7倍,与两倍工作量不符 2097152: t1 * t2 took 18.95 Q2: 仅慢1.8倍的原因是什么? 4194304: t1 * t2 took 86.161 Q3: 两倍工作量耗时慢4.5倍的原因是什么?
实验代码:
import torch import time from datetime import datetime from datetime import timedelta with torch.cuda.device(0): dim1 = 256 dim2 = 16 while dim2 <= 16384: t1 = 1 + torch.rand((dim1,dim2), device='cuda', dtype=torch.float64)/10000 t2 = 1 + torch.rand((dim1,dim2), device='cuda', dtype=torch.float64)/10000 i = 0 tm0 = datetime.now() while i < 1000000: t1 = t1 * t2 #torch.cuda.synchronize() # MULT is dependent on previous result i += 1 torch.cuda.synchronize() print(f"{dim1*dim2}: t1 * t2 took {round(timedelta.total_seconds(datetime.now()-tm0)+.0001, 3)}") dim2 *= 2
以下是对各性能异常问题的解析:
核心问题解析
Q1:数组规模远超CUDA核心数为何耗时仍约2秒?
RTX 4090的FP64核心数仅192,但你的代码存在强操作依赖:每次t1 = t1 * t2的结果必须依赖上一次运算的输出,GPU无法并行执行这100万次乘法,只能串行处理。
在数组规模≤65536时,单次乘法的计算时间远小于GPU的调度、流水线延迟,且数据完全驻留在L2缓存(RTX 4090 L2为24GB,65536个FP64元素仅占512KB),内存访问延迟可忽略。此时100万次串行操作的总耗时由GPU指令流水线的固有延迟主导,而非计算核心数量,因此数组规模翻倍后耗时几乎不变。
关于32768规模预期不符的问题
本质和Q1原因一致:32768个FP64元素仅占256KB,完全在L2缓存范围内,内存访问无额外开销。100万次串行乘法的总耗时由依赖链的流水线延迟决定,而非计算量,因此规模翻倍后耗时没有按预期增长。
Q2:1048576→2097152规模仅慢1.8倍的原因是什么?
这两个规模的数组分别占用8MB、16MB,仍能完全驻留L2缓存。此时单次乘法的计算量足够大,GPU计算核心被充分利用,同时CUDA的Warp调度和指令级并行可以在处理当前乘法的同时,隐藏部分内存访问延迟,使得实际耗时增长略低于线性(2倍)。此外PyTorch针对不同规模数组的内核调度优化,也进一步缩小了耗时差距。
Q3:2097152→4194304规模耗时慢4.5倍的原因是什么?
4194304个FP64元素占用32MB,超出了单SM缓存容量,且无法完全驻留L2缓存,此时内存访问成为性能瓶颈:
- 每次乘法需要从全局内存读取数据,全局内存延迟是L2缓存的数十倍;
- 串行依赖的运算模式下,GPU无法通过并行计算隐藏内存延迟,导致单次乘法耗时大幅增加;
- 更大的数组会引发更多内存总线冲突,进一步降低内存访问效率,最终导致耗时增长远超过线性。
内容的提问来源于stack exchange,提问作者Dan Wood
相关产品推荐
相关产品推荐

