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

PyTorch 中contiguous函数使用详解和代码演示

在 PyTorch 中,contiguous() 是一个用于 张量内存布局优化 的函数。它的作用是在需要时返回一个内存布局为连续(contiguous)的张量,常用于 transpose、permute 等操作后。


一、为什么需要 contiguous()

PyTorch 的张量是以 行优先(row-major)顺序 存储的。当你对张量使用 transpose()permute() 等操作时,虽然张量的维度看起来改变了,但底层的内存并没有重新排列,只是修改了索引方式。

一些 PyTorch 函数(如 .view())要求输入张量必须是 连续的内存块,否则就会报错。


二、函数定义与用法

Tensor.contiguous(memory_format=torch.contiguous_format) → Tensor

返回值:

返回一个与当前张量具有相同数据但在内存中 连续排列 的副本。如果当前张量已经是连续的,就直接返回自身。


三、典型使用场景

1. view() 前需要 .contiguous()

x = torch.randn(2, 3, 4)
y = x.permute(1, 0, 2)  # 改变维度顺序
z = y.contiguous().view(3, 8)  # 安全 reshape

如果不加 .contiguous()

z = y.view(3, 8)  # ⚠️ 报错:RuntimeError: view size is not compatible with input tensor's size and stride

2. 使用 transpose() 后需要 .contiguous() 参与后续操作

a = torch.randn(10, 20)
b = a.transpose(0, 1)  # Not contiguous now
b = b.contiguous()     # 重新在内存中复制数据为连续块

四、查看是否是连续的

x.is_contiguous()

五、底层原理简要

PyTorch 张量有 .stride() 属性定义每一维的跳步。连续的张量满足:

x.stride()[i] = product(x.shape[i+1:])

一旦 .transpose() / .permute() 修改了维度顺序,这个规则就被破坏,因此 .contiguous() 会重新分配内存来确保是连续的。


六、contiguous()项目演示

下面是一个完整的 PyTorch 小项目,演示 .contiguous() 的必要性与作用。将看到在对张量进行 permute() 后,使用 .view() reshape 会失败,只有 .contiguous() 可以解决问题。

项目内容:张量维度变换与 .contiguous() 对比演示

项目结构:

contiguous_demo/
├── main.py
└── requirements.txt

requirements.txt

torch>=2.0

main.py

import torchdef describe_tensor(tensor, name):print(f"{name}: shape={tensor.shape}, strides={tensor.stride()}, is_contiguous={tensor.is_contiguous()}")def main():print("=== 创建张量 ===")x = torch.randn(2, 3, 4)  # 原始张量 shape [2, 3, 4]describe_tensor(x, "x")print("\n=== 进行 permute 操作(交换维度) ===")y = x.permute(1, 0, 2)  # shape: [3, 2, 4]describe_tensor(y, "y (after permute)")print("\n尝试 view reshape 到 [3, 8](不使用 contiguous)")try:z = y.view(3, 8)  # ⚠️ 报错:因为 y 的内存不是连续的except RuntimeError as e:print(f"RuntimeError: {e}")print("\n=== 使用 .contiguous() 后 reshape ===")y_contig = y.contiguous()describe_tensor(y_contig, "y_contig (after .contiguous())")z = y_contig.view(3, 8)describe_tensor(z, "z (reshaped)")print("\n✅ reshape 成功,结果如下:")print(z)if __name__ == "__main__":main()

运行方法

  1. 安装依赖:
pip install -r requirements.txt
  1. 运行程序:
python main.py

运行结果概览

将看到:

  • 原始张量是连续的;
  • permute() 后变成非连续;
  • 使用 .view() 报错;
  • .contiguous() 修复内存后成功 reshape。

小总结要点

操作是否连续能否 .view()
原始张量✅ 是✅ 是
permute()❌ 否❌ 报错
.contiguous()✅ 是✅ 是

总结记忆:

操作是否影响连续性?是否需要 .contiguous()
view()❗ 需要连续✅ 是
permute() / transpose()破坏连续性✅ 是
reshape()自动处理❌ 不需要(内部处理)
http://www.xdnf.cn/news/12592.html

相关文章:

  • 第4章——springboot自动配置
  • LabVIEW音频测试分析
  • ​React Hooks 的闭包陷阱问题
  • YoloV12改进策略:Block改进|TAB,融合组内自注意力(IASA)和组间交叉注意力(IRCA)|即插即用
  • spring:实例工厂方法获取bean
  • 408考研逐题详解:2009年第33题
  • 第22讲、Odoo18 QWeb 模板引擎详解
  • 【PCIe总线】 -- PCI、PCIe相关实现
  • 第十五届蓝桥杯单片机国赛
  • SQL-labs通关(level1-22)
  • 主流信创数据库对向量功能的支持对比
  • Vue Fragment vs React Fragment
  • Mysql-定时删除数据库中的验证码
  • Golang基础学习
  • 性能测试-jmeter实战2
  • 注意力热图可视化
  • Ubuntu 下开机自动执行命令的方法
  • win11无法打开.bat文件、打开.bat文件闪退解决方案,星露谷smapi mod安装时,.bat安装文件一闪而
  • CMake基础:构建流程详解
  • 变幻莫测:CoreData 中 Transformable 类型面面俱到(一)
  • 通过日志分析华为CangjieMagic智能体框架的工作机理
  • CAD2025安装教程与资源下载
  • AI 开发之 Python 编程技能
  • Redis 实现分布式锁:深入剖析与最佳实践(含Java实现)
  • Mybatis 拦截器 与 PageHelper 源码解析
  • ⚡️ Linux Docker 基本命令参数详解
  • Kafka 消息模式实战:从简单队列到流处理(二)
  • 深入浅出Docker
  • 【Go语言基础【14】】defer与异常处理(panic、recover)
  • C++学习-入门到精通【16】自定义模板的介绍