当前位置: 首页 > news >正文

pytorch中的原地与非原地操作

pytorch中的原地与非原地操作

前言

读ATD源码时,我突然对其中的一个写法产生了疑惑:

 def forward(self, x, x_size, params):return self.patch_embed(self.conv(self.patch_unembed(self.residual_group(x, x_size, params), x_size))) + x

这种写法真的可以实现残差连接吗?如果self.residual_group修改了x,那+x是不是也不是原本的x了?

(注明一下:这个东西要问deepseek R1 671b,AI-4o不明白这个点)

解答

首先明确一个很重要的点:PyTorch中的大多数操作都是 非原地的 ,比如卷积、线性层等,它们会返回新的张量,而不是修改输入

举个例子:

def forward(self, x):    
x = self.conv(x)
# 生成新的张量,原x不变    
x = self.relu(x)  # 同样生成新张量    
return x  

什么是 原地(inplace) 操作?

常见的原地操作包括:

  1. 使用inplace=True的激活函数,如nn.ReLU(inplace=True)
  2. 直接对张量进行赋值操作,例如x[:, :, ...] = ...x += ...
  3. 使用原地函数,如torch.add_torch.mul_等。

所以,现在可以回答开头的问题了

答案:这个残差是正确的。

阅读代码可以发现,只有self.conv是inplace的,而其他的模块都是非原地的。

self.conv 会修改 输入到 self.conv 的张量(即 self.patch_unembed 的输出),但 不会影响原始输入 x。因为输入到 self.conv 的张量是 self.patch_unembed(...) 的结果,与原始 x 无关。

不过,我觉得写成

def forward(self, x, x_size, params):original_x = x return self.patch_embed(self.conv(self.patch_unembed(self.residual_group(x, x_size, params), x_size))) + original_x

会更清晰且不容易出错。不然还得仔细检查中间的网络层到底有没有inplace操作

补充

pytorch/python的变量传参是原变量还是引用?值or址?

https://blog.csdn.net/weixin_42264234/article/details/118788863 (这个可以看看)

https://blog.csdn.net/u010167269/article/details/52073136 (这个不用看,没啥用)

我把最重要的点写在这:

def change(val):val.append(100)val = ['T', 'Z', 'Y']
nums = [0, 1]
change(nums)
print(nums)

结果是什么?为什么?

在 Python 中,函数参数的传递是按对象引用传递的(✅)。这意味着函数内部对可变对象(如列表)的修改会影响到函数外部的对象。然而,如果在函数内部重新绑定参数到一个新的对象,这个改变不会影响到函数外部的对象。

让我们逐步分析代码:

  1. nums = [0, 1]:创建一个列表 nums,其中包含两个元素 [0, 1]
  2. change(nums):调用 change 函数,并将 nums 作为参数传递进去。
  3. 在change函数内部:
    • val.append(100):将 100 添加到 val 所引用的列表中。此时,valnums 仍然引用同一个列表,所以 nums 变为 [0, 1, 100]
    • val = ['T', 'Z', 'Y']:将 val 重新绑定到一个新的列表 ['T', 'Z', 'Y']。这个操作不会影响到 nums,因为 val 现在引用的是一个新的对象。
  4. print(nums):打印 nums 的值。由于在 change 函数内部对 val 的修改影响了 nums,所以 nums 现在是 [0, 1, 100]

因此,代码的输出是:

[0, 1, 100]

总结:nums 的值被修改为 [0, 1, 100],因为在 change 函数内部通过 val.append(100) 修改了 nums 所引用的列表。而 val = ['T', 'Z', 'Y'] 这一行只是将 val 重新绑定到一个新的列表,并没有影响到 nums

相关文章:

  • 软件系统验收报告:功能、性能稳定性如何?数据导出卡顿咋回事?
  • GPU集群中的超节点
  • 【Hot 100】 148. 排序链表
  • AI Engine Kernel and GraphProgramming--知识分享1
  • 从有线到无线:冶炼工厂的高效转型
  • 视觉问答论文解析:《Skywork R1V2: Multimodal Hybrid Reinforcement Learning for Reasoning》
  • 数电发票整理:免费实用工具如何高效解析 XML 发票数据
  • 数据采集,埋点模型
  • 论文公式根据章节自动编号教程
  • 阿里云服务迁移实战: 06-切换DNS
  • 10.idea中创建springboot项目_jdk17
  • 大连理工大学选修课——机器学习笔记(1):概述
  • 【Agent】MCP协议 | 用高德MCP Server制作旅游攻略
  • Java 表达式及运算符的优先级与结合性入门
  • Windows 10 环境二进制方式安装 MySQL 8.0.41
  • 异步协程中基于 aiomysql 的异步数据库操作
  • 第五部分:进阶项目实战
  • 2025平航杯—团队赛
  • c#确定按钮5秒自动确定
  • 涨薪技术|0到1学会性能测试第44课-apachetop模块监控
  • 乌副总理:乌美签署矿产协议
  • 证监会:坚决拥护党中央对王建军进行纪律审查和监察调查决定
  • 辽宁辽阳市白塔区一饭店发生火灾,当地已启动应急响应机制
  • 特朗普执政百日集会吹嘘政绩,美国消费者信心指数跌至疫情以来最低
  • 李铁案二审驳回上诉,维持一审有期徒刑20年的判决
  • 陈文清:推进扫黑除恶常态化走深走实,有力回应人民群众对安居乐业的新期待