【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.10 ndarray内存模型:从指针到缓存优化

在这里插入图片描述

2.10 ndarray内存模型:从指针到缓存优化

目录
《ndarray内存模型:从指针到缓存优化》
2.10.1 ndarray结构体解析
2.10.2 数据指针操作
2.10.3 缓存行对齐技巧
2.10.4 指针操作风险
2.10.5 大数组内存预分配策略
2.10.6 总结
2.10.7 参考文献
2.10.1 ndarray结构体解析

NumPy 的 ndarray 是一个高效的多维数组对象,它在内存中的存储方式对性能有重要影响。理解 ndarray 的内部结构有助于更好地优化代码性能。

  • C结构体源码解析:NumPy 的 C 源码中 ndarray 的结构体定义。
  • 内存布局ndarray 的内存布局。
  • ** strides 和 shape**:stridesshape 属性的详细解释。
ndarray
+int nd: 维度数
+npy_intp* dimensions: 形状数组
+npy_intp* strides: 步长数组
+void* data: 数据指针
+PyDataTypeObject* dtype: 数据类型
+PyObject* base: 基数组
+int flags: 标志位
import numpy as np# 创建一个 3x3 的数组
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(f"数组 a 的形状: {a.shape}")  # 输出数组的形状
print(f"数组 a 的步长: {a.strides}")  # 输出数组的步长
print(f"数组 a 的数据类型: {a.dtype}")  # 输出数组的数据类型
2.10.2 数据指针操作

ndarray 的数据指针(data)是 C 语言中的 void* 指针,指向实际数据在内存中的存储位置。了解数据指针操作可以更好地优化内存访问。

  • 数据指针的基本操作:如何访问和操作 ndarray 的数据指针。
  • 内存视图:创建和使用内存视图。
  • 内存连续性:检查和确保内存连续性。
import numpy as np# 创建一个 3x3 的数组
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.int32)# 获取数据指针
data_ptr = a.ctypes.data  # 获取数组的 C 数据指针
print(f"数组 a 的数据指针: {data_ptr}")  # 输出数据指针# 检查内存连续性
print(f"数组 a 是否是 C 内存连续的: {a.flags['C_CONTIGUOUS']}")  # 输出 C 内存连续性标志
print(f"数组 a 是否是 Fortran 内存连续的: {a.flags['F_CONTIGUOUS']}")  # 输出 Fortran 内存连续性标志
2.10.3 缓存行对齐技巧

缓存行对齐是提高数据访问性能的关键技术之一。在 NumPy 中,通过合理的数组形状和步长设置,可以实现缓存行对齐,从而提高计算效率。

  • 缓存行对齐的原理:缓存行对齐的基本原理。
  • 缓存行大小:常见的缓存行大小及其影响。
  • 实现缓存行对齐:如何在 NumPy 中实现缓存行对齐。
缓存行对齐原理
提高数据访问效率
减少缓存缺失
优化计算性能
合理设置数组形状
调整步长
使用内存视图
import numpy as np# 创建一个 3x1000 的数组
a = np.random.rand(3, 1000)# 检查步长
print(f"数组 a 的步长: {a.strides}")  # 输出步长# 调整数组形状以实现缓存行对齐
aligned_a = np.asfortranarray(a)  # 转换为 Fortran 内存顺序
print(f"缓存行对齐后的数组 a 的步长: {aligned_a.strides}")  # 输出调整后的步长
2.10.4 指针操作风险

指针操作虽然强大,但也存在潜在的风险,特别是在处理多维数组时。了解这些风险可以帮助避免常见的错误。

  • 越界访问:数据指针越界访问的风险。
  • 未初始化内存:使用未初始化内存的风险。
  • 数据类型不匹配:数据类型不匹配的风险。
指针操作风险
越界访问
未初始化内存
数据类型不匹配
导致程序崩溃
产生错误结果
引发数据混乱
import numpy as np# 创建一个 3x3 的数组
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.int32)# 获取数据指针
data_ptr = a.ctypes.data# 越界访问
try:value = np.ctypeslib.as_array(np.ctypeslib.c_int32.from_address(data_ptr + 12 * a.itemsize))  # 越界访问print(f"越界访问的值: {value}")
except ValueError as e:print(f"错误: {e}")  # 输出错误信息# 未初始化内存
uninitialized_a = np.empty((3, 3), dtype=np.int32)
print(uninitialized_a)  # 输出未初始化的数组# 数据类型不匹配
b = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]], dtype=np.float64)
try:value = np.ctypeslib.as_array(np.ctypeslib.c_int32.from_address(b.ctypes.data))print(f"数据类型不匹配的值: {value}")
except ValueError as e:print(f"错误: {e}")  # 输出错误信息
2.10.5 大数组内存预分配策略

在处理大数组时,合理的内存预分配策略可以显著提高性能,避免频繁的内存分配和释放操作。

  • 预分配的好处:内存预分配的好处。
  • 使用 np.emptynp.zeros:如何使用 np.emptynp.zeros 进行内存预分配。
  • 动态增长数组:如何动态增长数组。
大数组内存预分配策略
提高性能
减少内存碎片
避免频繁分配
使用 np.empty 和 np.zeros
动态增长数组
import numpy as np# 使用 np.empty 进行内存预分配
pre_allocated_array = np.empty((10000, 10000), dtype=np.float32)
print(f"预分配的数组: {pre_allocated_array}")  # 输出预分配的数组# 使用 np.zeros 进行内存预分配
zero_array = np.zeros((10000, 10000), dtype=np.float32)
print(f"预分配的零数组: {zero_array}")  # 输出预分配的零数组# 动态增长数组
def dynamic_array_growth(size):array = np.empty((0, size), dtype=np.float32)for i in range(10):new_row = np.random.rand(1, size)array = np.vstack((array, new_row))return arraydynamic_array = dynamic_array_growth(10000)
print(f"动态增长的数组: {dynamic_array}")  # 输出动态增长的数组
2.10.6 总结
  • 关键收获:理解 ndarray 的内存模型和缓存行对齐技巧。
  • 最佳实践:合理的数据指针操作和内存预分配策略。
  • 常见陷阱:指针操作中的常见风险及其解决方法。

通过本文,我们深入探讨了 ndarray 的内存模型,包括其结构体解析、数据指针操作、缓存行对齐技巧、指针操作风险以及大数组内存预分配策略。希望这些内容能帮助你在实际开发中更好地优化代码性能,避免常见的内存陷阱。

2.10.7 参考文献
参考资料链接
《NumPy Beginner’s Guide》NumPy Beginner’s Guide
《Python for Data Analysis》Python for Data Analysis
NumPy 官方文档NumPy C API Documentation
TensorFlow 官方文档TensorFlow Performance Guide
《高性能Python》High Performance Python
《Python数据科学手册》Python Data Science Handbook
Stack OverflowUnderstanding NumPy’s C API
MediumOptimizing NumPy Memory Usage
SciPy 官方文档SciPy Memory Efficiency
WikipediaCache Alignment
量子力学教程Quantum Mechanics Lecture Notes
《Numerical Linear Algebra》Numerical Linear Algebra

这篇文章包含了详细的原理介绍、代码示例、源码注释以及案例等。希望这对您有帮助。如果有任何问题请随私信或评论告诉我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/67804.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

80-《红球姜》

红球姜 红球姜(学名:Zingiber zerumbet (L.) Smith)是姜科姜属多年生草本植物,根茎块状,株高可达2米。叶片披针形至长圆状披针形,无柄或短柄;总花梗长可达30厘米,花序球果状&#xf…

UE 5.3 C++ 对垃圾回收的初步认识

一.UObject的创建 UObject 不支持构造参数。 所有的C UObject都会在引擎启动的时候初始化,然后引擎会调用其默认构造器。如果没有默认的构造器,那么 UObject 将不会编译。 有修改父类参数的需求,就使用指定带参构造 // Sets default value…

点击WPS 任务栏上的图标,不是马上进入工作页面,而是呈现多个文档页面选择时的处理方法

问题: 点击WPS以后不是直接进入 解决: 首页-配置和修复工具-高级-兼容设置-改为与microsoft office 2010兼容(D)

【自然语言处理(NLP)】基于Transformer架构的预训练语言模型:BERT 训练之数据集处理、训练代码实现

文章目录 介绍BERT 训练之数据集处理BERT 原理及模型代码实现数据集处理导包加载数据生成下一句预测任务的数据从段落中获取nsp数据生成遮蔽语言模型任务的数据从token中获取mlm数据将文本转换为预训练数据集创建Dataset加载WikiText-2数据集 BERT 训练代码实现导包加载数据构建…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.5 高级索引应用:图像处理中的区域提取

2.5 高级索引应用:图像处理中的区域提取 目录/提纲 #mermaid-svg-BI09xc20YqcpUam7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-BI09xc20YqcpUam7 .error-icon{fill:#552222;}#mermaid-svg-BI09xc20…

通过Redisson构建延时队列并实现注解式消费

目录 一、序言二、延迟队列实现1、Redisson延时消息监听注解和消息体2、Redisson延时消息发布器3、Redisson延时消息监听处理器 三、测试用例四、结语 一、序言 两个月前接了一个4万的私活,做一个线上商城小程序,在交易过程中不可避免的一个问题就是用户…

Baklib构建高效协同的基于云的内容中台解决方案

内容概要 随着云计算技术的飞速发展,内容管理的方式也在不断演变。企业面临着如何在数字化转型过程中高效管理和协同处理内容的新挑战。为应对这些挑战,引入基于云的内容中台解决方案显得尤为重要。 Baklib作为创新型解决方案提供商,致力于…

deepseek+vscode自动化测试脚本生成

近几日Deepseek大火,我这里也尝试了一下,确实很强。而目前vscode的AI toolkit插件也已经集成了deepseek R1,这里就介绍下在vscode中利用deepseek帮助我们完成自动化测试脚本的实践分享 安装AI ToolKit并启用Deepseek 微软官方提供了一个针对AI辅助的插件,也就是 AI Toolk…

电介质超表面中指定涡旋的非线性生成

涡旋光束在众多领域具有重要应用,但传统光学器件产生涡旋光束的方式限制了其在集成系统中的应用。超表面的出现为涡旋光束的产生带来了新的可能性,尤其是在非线性领域,尽管近些年来已经有一些研究,但仍存在诸多问题,如…

基于Springboot+mybatis+mysql+html图书管理系统2

基于Springbootmybatismysqlhtml图书管理系统2 一、系统介绍二、功能展示1.用户登陆2.用户主页3.图书查询4.还书5.个人信息修改6.图书管理(管理员)7.学生管理(管理员)8.废除记录(管理员) 三、数据库四、其它…

本地部署DeepSeek方法

本地部署完成后的效果如下图,整体与chatgpt类似,只是模型在本地推理。 我们在本地部署主要使用两个工具: ollamaopen-webui ollama是在本地管理和运行大模型的工具,可以直接在terminal里和大模型对话。open-webui是提供一个类…

游戏引擎 Unity - Unity 启动(下载 Unity Editor、生成 Unity Personal Edition 许可证)

Unity Unity 首次发布于 2005 年,属于 Unity Technologies Unity 使用的开发技术有:C# Unity 的适用平台:PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域:开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…

【开源免费】基于Vue和SpringBoot的公寓报修管理系统(附论文)

本文项目编号 T 186 ,文末自助获取源码 \color{red}{T186,文末自助获取源码} T186,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

《苍穹外卖》项目学习记录-Day11订单统计

根据起始时间和结束时间,先把begin放入集合中用while循环当begin不等于end的时候,让begin加一天,这样就把这个区间内的时间放到List集合。 查询每天的订单总数也就是查询的时间段是大于当天的开始时间(0点0分0秒)小于…

【python】python油田数据分析与可视化(源码+数据集)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 【python】python油田数据分析与可视化&#xff08…

FBX SDK的使用:基础知识

Windows环境配置 FBX SDK安装后,目录下有三个文件夹: include 头文件lib 编译的二进制库,根据你项目的配置去包含相应的库samples 官方使用案列 动态链接 libfbxsdk.dll, libfbxsdk.lib是动态库,需要在配置属性->C/C->预…

一文讲解HashMap线程安全相关问题(上)

HashMap不是线程安全的,主要有以下几个问题: ①、多线程下扩容会死循环。JDK1.7 中的 HashMap 使用的是头插法插入元素,在多线程的环境下,扩容的时候就有可能导致出现环形链表,造成死循环。 JDK 8 时已经修复了这个问…

python学习——常用的内置函数汇总

文章目录 类型转换函数数学函数常用的迭代器操作函数常用的其他内置函数 类型转换函数 数学函数 常用的迭代器操作函数 实操: from cv2.gapi import descr_oflst [55, 42, 37, 2, 66, 23, 18, 99]# (1) 排序操作 asc_lst sorted(lst) # 升序 desc_lst sorted(l…

MySQL数据库环境搭建

下载MySQL 官网:https://downloads.mysql.com/archives/installer/ 下载社区版就行了。 安装流程 看b站大佬的视频吧:https://www.bilibili.com/video/BV12q4y1477i/?spm_id_from333.337.search-card.all.click&vd_source37dfd298d2133f3e1f3e3c…

如何用微信小程序写春联

​ 生活没有模板,只需心灯一盏。 如果笑能让你释然,那就开怀一笑;如果哭能让你减压,那就让泪水流下来。如果沉默是金,那就不用解释;如果放下能更好地前行,就别再扛着。 一、引入 Vant UI 1、通过 npm 安装 npm i @vant/weapp -S --production​​ 2、修改 app.json …