Python torch如何在几乎零的时间内将两个10000*10000矩阵相乘?为什么速度从349毫秒下降到999µ;s
以下是Jupyter的摘录: 在Python torch如何在几乎零的时间内将两个10000*10000矩阵相乘?为什么速度从349毫秒下降到999µ;s,python,performance,jupyter-notebook,pytorch,Python,Performance,Jupyter Notebook,Pytorch,以下是Jupyter的摘录: 在[1]中: 导入火炬,numpy作为np,datetime cuda=火炬装置(“cuda”) 在[2]中: ac=torch.randn(10000,10000).to(cuda) bc=火炬。兰登(10000,10000)。至(cuda) %时间cc=火炬。马特穆尔(ac,bc) 打印(cc[0,0],torch.sum(ac[0,:]*bc[:,0])) 墙壁时间:349毫秒 张量(17.0374,device='cuda:0')张量(17.0376,d
[1]
中:
导入火炬,numpy作为np,datetime
cuda=火炬装置(“cuda”)
在[2]
中:
ac=torch.randn(10000,10000).to(cuda)
bc=火炬。兰登(10000,10000)。至(cuda)
%时间cc=火炬。马特穆尔(ac,bc)
打印(cc[0,0],torch.sum(ac[0,:]*bc[:,0]))
墙壁时间:349毫秒
张量(17.0374,device='cuda:0')张量(17.0376,device='cuda:0'))
时间较短,但仍然合理(1e12乘法为0.35秒)
但如果我们重复同样的话:
ac=torch.randn(10000,10000).to(cuda)
bc=火炬。兰登(10000,10000)。至(cuda)
%时间cc=火炬。马特穆尔(ac,bc)
打印(cc[0,0],torch.sum(ac[0,:]*bc[:,0]))
壁时间:999µs
张量(-78.7172,装置='cuda:0')张量(-78.7173,装置='cuda:0'))
1e12
在1ms
中进行乘法
为什么时间从349ms变为1ms
信息:
- 在GeForce RTX 2070上测试李>
- 可以在Google Colab上复制
- 发件人:
- 发件人:
我猜是GPU内存缓存。每次运行后,请尝试torch.cuda.empty_cache() 已在讨论PyTorch:上对此进行了讨论 我想强调该帖子中的两条评论:
基本上,您必须
synchronize()
才能进行正确的测量:
导入火炬
x=火炬。兰登(10000,10000)。至(“cuda”)
w=torch.randn(10000,10000)至(“cuda”)
#确保在开始测量时间之前完成上下文初始化
torch.cuda.synchronize()
%时间y=x.mm(w.t());torch.cuda.synchronize()
CPU时间:用户288毫秒,系统191毫秒,总计479毫秒
墙壁时间:492毫秒
x=torch.randn(10000,10000).to(“cuda”)
w=torch.randn(10000,10000)至(“cuda”)
#确保在开始测量时间之前完成上下文初始化
torch.cuda.synchronize()
%时间y=x.mm(w.t());torch.cuda.synchronize()
CPU时间:用户237毫秒,系统231毫秒,总计468毫秒
墙壁时间:469毫秒
医生说:
torch.cuda.synchronize()
等待CUDA设备上所有流中的所有内核完成
事实上,这告诉Python:停止,等待操作完全完成
否则,%时间将在发出命令后立即返回。
这将是测试时间的正确方法。注意两次torch.cuda.synchronize()
第一次等待张量在cuda上移动,第二次等待命令在GPU上完成
import torch
x = torch.randn(10000, 10000).to("cuda")
w = torch.randn(10000, 10000).to("cuda")
torch.cuda.synchronize()
%timeit -n 10 y = x.matmul(w.t()); torch.cuda.synchronize() #10 loops, best of 3: 531 ms per loop
我也想过,但是
ac
和bc
应该是随机的。这在某种程度上仍然有效吗?我只是尝试了一下,empty\u cache(…)
在这种情况下没有效果。只释放未使用的缓存内存,因此您可能希望滑入delac;德尔bc;在清空\u缓存之前删除cc
。也可能是pytorch从GPU请求更多内存,因此您可能希望在操作前后进行监视。@a_guest我还尝试了del
变量,但仍然是相同的计时。。。这不是我的问题,但我对为什么会这样感兴趣happens@a_guest是的,如果没有同步(…)
,则计时不可靠。我以社区维基的形式发布了一个答案,因为它基本上来自于讨论PyTorch线程。在Google Colab上尝试了这个代码,看起来大约400 ms
是一个合理的持续时间。我认为这是正确的答案。@Iyunb事实上,我在答案上发布的测量值来自Google Colab:)顺便说一句,答案是一个社区wiki,因为它基本上来自与另一个用户(一位访客)进行了一次小讨论后的讨论PyTorch线程关于另一个答案的评论。CUDA最佳实践指南的这一部分可能与此相关:它明确解释了异步调用的问题以及可能需要的同步化。进行矩阵乘法的明显方法是O(N^3),但是否有一种更快的方法,可能是O(N^2*log(N))在O(N^(2*log(N)))中没有已知的方法来实现这一点。从理论上讲,有一些方法可以更快地实现这一点,但在实践中,它们是不可用的,除了一种方法,它取N**(log(7)/log(2)),约为N**2.81,但由于大常数和数值稳定性问题,甚至没有使用它。谢谢。这可能是我记错的。