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

NumPy/PyTorch/C char数组内存排布

1. 关于 np.random.randn(2, 3) 的数据存储

  • 数据类型 (Data Type)np.random.randn 默认生成的是 64位(8字节)双精度浮点数 (numpy.float64)。所以每个数字占 8个字节,而不是8位(1字节)。这是一个关键区别。

  • 内存布局 (Memory Layout):默认情况下,NumPy数组使用 C-style (row-major) 的顺序 在内存中紧凑地(contiguously) 存储数据。

对于一个 (2, 3) 的矩阵,其内存布局如下所示:

text

[ [a, b, c], [d, e, f] ]

在内存中的排列是连续的:a -> b -> c -> d -> e -> f。每个元素紧挨着下一个元素,中间没有空隙。

所以,是的,np.random.randn(2, 3) 创建的数据是像C语言数组一样,以行主序、紧凑的方式存放在系统内存中的,每个元素占8字节。

可以通过以下属性验证:

python

import numpy as nparr = np.random.randn(2, 3)
print(arr.dtype)      # 输出:float64
print(arr.itemsize)   # 输出:8 (每个元素占8字节)
print(arr.flags)
# 输出中会看到:
#   C_CONTIGUOUS : True  (C风格连续)
#   F_CONTIGUOUS : False (Fortran风格不连续)
#   OWNDATA : True       (数组拥有自己的数据)

2. 关于数据转换时的重新排布

答案是:大多数情况下会,但这取决于转换的源和目标。 核心在于 内存布局的连续性 和 数据类型的匹配

情况一:NumPy数组之间的转换(例如视图 vs. 拷贝)
  • arr.astype(np.float32):这会重新排布。它创建了一个全新的数组,分配了新的内存,并将原float64数据逐个转换为float32再存入。新老数组内存不共享。

  • arr.view(np.float32):这创建的是一个视图。它不会重新排布原始float64数据的字节,而是用新的数据类型(float32)去解释同一块内存。因为float32是4字节,所以一个float64(8字节)会被解释成两个float32数,结果通常是无意义的数据。这很危险,但速度快,不拷贝数据。

  • arr.T(转置):对于C连续的数组,转置操作默认返回一个视图,但它的内存布局不再是C连续的(变成了F连续的)。访问它可能会更慢,但并没有发生数据拷贝和重新排布。如果你调用 arr.T.copy(),则会强制进行拷贝和重新排布,得到一个C连续的新数组。

情况二:NumPy 与 PyTorch Tensor 的转换

这是非常常见且容易引起性能问题的场景。

  • torch.from_numpy(numpy_arr)

    • 这是最高效的方式。PyTorch 和 NumPy 可以共享底层内存(前提是都在CPU上,且数据类型兼容)。

    • PyTorch Tensor 会直接使用 NumPy 数组的底层数据缓冲区,不会重新排布或拷贝数据

    • 重要条件:NumPy数组必须是紧凑连续的。如果NumPy数组是不连续的(例如,通过切片arr[:, ::2]得到的),torch.from_numpy会失败或被迫拷贝数据。

    • 共享内存意味着,修改一个会影响另一个。

  • torch.tensor(numpy_arr)

    • 这个操作总是会拷贝数据。它会分配新的PyTorch内存,并将NumPy数组的数据复制过去。

    • 即使用于紧凑连续的数组,它也会拷贝。这是为了确保新Tensor完全独立于原来的NumPy数组。

结论:在NumPy和PyTorch间转换时,为了效率应优先使用 torch.from_numpy 并确保NumPy数组是连续的。如果不需要共享内存,则用 torch.tensor

情况三:与C语言char数组的转换

这通常涉及序列化/反序列化与底层C代码交互

  • 从C char数组到NumPy/PyTorch

    • 如果你有一个C char数组(本质是一段原始的字节缓冲区void* + 长度),并且你知道这段内存的数据类型和形状,你可以让NumPy/PyTorch直接“接管”这段内存

    • NumPynp.frombuffer 或 np.ndarray 的构造函数。可以创建一个视图,将字节缓冲区解释为指定数据类型和形状的数组。不重新排布数据,零拷贝

    • PyTorchtorch.frombuffer (较新版本) 或 torch.from_numpy(np.frombuffer(...))。同样旨在实现零拷贝。

    • 风险:你必须绝对保证C数组的内存布局(字节顺序、连续性)与你要创建的数组的要求完全匹配,否则数据解释会是错误的。

  • 从NumPy/PyTorch到C char数组

    • 本质上就是获取数组底层数据缓冲区的指针。

    • NumPyarr.data 或 arr.__array_interface__[‘data’][0]

    • PyTorchtensor.data_ptr()

    • 你可以将这个指针传递给C函数,C函数就可以直接读写这块内存。同样,前提是Tensor在内存中是紧凑连续的,否则C代码访问到的数据布局会和预期不符。


总结

操作是否会重新排布/拷贝数据?说明
np.random.randn(2,3)创建紧凑、C连续的float64数组
arr.astype(new_dtype)创建新数组,拷贝并转换数据
arr.view(new_dtype)创建视图,重新解释原有数据(危险)
arr.T创建转置视图,但布局可能改变
torch.from_numpy(arr)通常否零拷贝共享内存,要求arr连续
torch.tensor(arr)总是拷贝数据,创建独立Tensor
与C数组互转通常否通过np.frombuffer/torch.frombuffer或直接获取指针,零拷贝,但对内存布局有严格要求

核心思想:高性能计算库(NumPy, PyTorch)在与自身或其他库交互时,会尽可能地避免数据拷贝(零拷贝),而是通过共享内存来实现高效操作。能否实现零拷贝的关键在于内存布局(尤其是连续性)和数据类型的兼容性。如果布局或类型不匹配,框架就不得不进行昂贵的数据拷贝和重新排布。

http://www.dtcms.com/a/353182.html

相关文章:

  • 网站防爆破安全策略分析
  • python项目开发:创建虚拟环境
  • 利用机器学习优化Backtrader策略原理与实践
  • 深入解析函数栈帧创建与销毁
  • 斯塔克工业技术日志:用基础模型打造 “战甲级” 结构化 AI 功能
  • 预测模型及超参数:1.传统机器学习:SVR与KNN
  • 网页版云手机怎么样
  • Enduro 克隆游戏 — 基于 HTML、CSS 与 JavaScript 的完整教程模板
  • 23种设计模式——单例模式(Singleton)​详解
  • 金仓数据库文档系统全面升级:用户体验焕然一新
  • CPU、IO、网络与内核参数调优
  • Linux 性能调优实战:CPU、磁盘 I/O、网络与内核参数
  • 系统架构设计师备考第8天——嵌入式系统
  • 工业网络安全:保护制造系统和数据
  • Linux 系统CPU-IO-网络-内核参数的调优
  • 【学习笔记】GB 42250-2022标准解析
  • 手写MyBatis第36弹:MyBatis执行流程中SQL命令类型解析
  • Effective c++ 35条款详解
  • docker run 后报错/bin/bash: /bin/bash: cannot execute binary file总结
  • Python计算点云的欧式、马氏、最近邻、平均、倒角距离(Chamfer Distance)
  • iOS技术之通过Charles抓包http、https数据
  • 【开题答辩全过程】以Trlig(服装网站)为例,包含答辩的问题和答案
  • ETH PPS 配置链路
  • 车载诊断架构 --- 基于整车功能的正向诊断需求开发
  • Ruoyi-cloud 微服务部署双方案:本地与 K8S 实践手册
  • FastAPI + SQLModel 从 0 搭到完整 CRUD
  • 腾讯云人脸库技术架构深度解析
  • Github 3k+ star,中后台管理系统框架,支持多款 UI 组件库,兼容PC、移动端!比商业系统还专业!!
  • IntelliJ IDEA Debug 模式功能指南
  • 微算法科技(NASDAQ:MLGO)突破性FPGA仿真算法技术助力Grover搜索,显著提升量子计算仿真效率