PyTorch中为何a.grad的内存地址(ID)未发生变化?
为什么
a.grad的内存地址(ID)没有变化? 这背后是PyTorch针对梯度张量的内存优化逻辑,我们一步步拆解你的代码来理解:
梯度张量的初始创建:当你执行
los.backward()后,PyTorch会为a生成一个梯度张量a.grad,值为[5.0, 5.0, 5.0],此时这个张量在内存中拥有唯一的ID(也就是你打印的第一个数值)。赋值操作的特殊优化:当你执行
a.grad = torch.tensor([1., 2., 3.])时,PyTorch并没有直接让a.grad指向新创建的张量对象,而是做了内存友好的处理:- 检查新张量和原有
a.grad的形状、数据类型、设备是否完全匹配 - 如果三者都匹配,PyTorch会直接将新张量的数据原地复制到原有
a.grad的内存空间中,不会创建新的张量对象 - 这就导致
a.grad始终指向同一个内存对象,因此ID保持不变
- 检查新张量和原有
验证机制的小实验:如果故意创建一个形状/类型不匹配的张量赋值给
a.grad,就能看到ID变化:import torch a = torch.tensor([1.0, 2.0, 3.0], requires_grad=True) b = torch.tensor([5.0, 5.0, 5.0]) los = sum(a*b) los.backward() print(id(a.grad)) # 赋值一个形状不同的张量 a.grad = torch.tensor([1., 2.]) print(id(a.grad))此时两次打印的ID会完全不同——因为PyTorch无法在原有张量的内存空间中容纳新数据,只能创建新的张量对象并让
a.grad指向它。
另外补充:如果想要强制替换a.grad的引用(让它指向全新的张量对象),可以先删除原有梯度再赋值:
del a.grad a.grad = torch.tensor([1., 2., 3.])
这时打印ID就会发现和之前的结果不同了。
内容的提问来源于stack exchange,提问作者shelvey jiang
相关产品推荐
相关产品推荐

