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

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.11 视图与副本:内存优化的双刃剑

在这里插入图片描述

2.11 视图与副本:内存优化的双刃剑

目录
《视图与副本:内存优化的双刃剑》
2.11.1 视图创建条件检测
2.11.2 副本深度拷贝机制
2.11.3 内存占用实时监控
2.11.4 内存泄漏预防
2.11.5 Dask集成案例
2.11.6 总结
2.11.7 参考文献
2.11.1 视图创建条件检测

在 NumPy 中,数组操作可以创建视图或副本。视图不创建新的数据副本,而是共享原始数组的数据,因此对内存占用较小。副本则会创建新的数据副本,占用更多的内存。了解视图和副本的创建条件对于优化内存使用至关重要。

  • 视图与副本的区别:视图和副本的基本概念。
  • 视图创建条件:哪些操作会创建视图。
  • 副本创建条件:哪些操作会创建副本。
  • 检测方法:如何检测视图和副本。
import numpy as np

# 创建一个原始数组
a = np.array([1, 2, 3, 4, 5, 6])

# 视图操作
b = a[1:4]  # 使用切片操作创建视图
print(f"b 是否是 a 的视图: {np.may_share_memory(a, b)}")  # 检测 b 是否是 a 的视图

# 副本操作
c = a.copy()  # 使用 copy 方法创建副本
print(f"c 是否是 a 的副本: {np.may_share_memory(a, c)}")  # 检测 c 是否是 a 的副本
2.11.2 副本深度拷贝机制

副本的深度拷贝机制确保了数据的独立性,但在处理大数组时会消耗较多内存。了解深度拷贝的实现原理和优化方法可以提高代码性能。

  • 深度拷贝的实现原理copy 方法的实现原理。
  • 优化方法:如何优化深度拷贝操作。
  • 使用 np.ascontiguousarray:优化内存布局。
通过 copy 方法创建副本
ndarray
+int nd: 维度数
+npy_intp* dimensions: 形状数组
+npy_intp* strides: 步长数组
+void* data: 数据指针
+PyDataTypeObject* dtype: 数据类型
+PyObject* base: 基数组
+int flags: 标志位
copy
+ndarray* _copy: 拷贝后的数组
+void* _data: 新的数据指针
+npy_intp* _strides: 新的步长数组
+int _flags: 新的标志位
import numpy as np

# 创建一个原始数组
a = np.array([[1, 2, 3], [4, 5, 6]])

# 深度拷贝
b = a.copy()
b[0, 0] = 10  # 修改副本中的值
print(f"原始数组 a: \n{a}")  # 原始数组不受影响
print(f"副本数组 b: \n{b}")  # 副本数组被修改

# 使用 np.ascontiguousarray 优化内存布局
c = np.ascontiguousarray(a)
print(f"优化后的数组 c: \n{c}")  # 确保内存连续
2.11.3 内存占用实时监控

实时监控内存占用可以帮助你及时发现并解决内存泄漏问题。使用 memory_profiler 工具可以方便地进行内存监控。

  • memory_profiler 安装:如何安装 memory_profiler
  • 内存监控方法:使用 memory_profiler 进行内存监控。
  • 内存泄漏检测:如何检测内存泄漏。
内存占用实时监控
memory_profiler 安装
使用 memory_profiler 进行内存监控
检测内存泄漏
# 使用 memory_profiler 进行内存监控
from memory_profiler import profile

@profile
def memory_intensive_function():
    a = np.random.rand(10000, 10000)  # 创建一个大数组
    b = a.copy()  # 创建副本
    del a  # 删除原始数组
    c = b[1:1000, 1:1000]  # 创建视图
    del b  # 删除副本
    return c

result = memory_intensive_function()
print(f"结果数组: \n{result}")  # 输出结果数组
2.11.4 内存泄漏预防

内存泄漏是指程序在运行过程中未能释放不再使用的内存,导致内存占用不断增加。了解内存泄漏的原因和预防方法可以提高代码的稳定性和性能。

  • 内存泄漏的原因:常见的内存泄漏原因。
  • 预防方法:如何预防内存泄漏。
  • 使用 Dask 进行内存管理:Dask 的内存管理机制。
内存泄漏预防
内存泄漏的原因
未释放的内存
循环引用
隐式内存分配
预防方法
及时释放内存
避免循环引用
使用 Dask 进行内存管理
自动释放内存
分块处理数据
import numpy as np
import dask.array as da

# 创建一个大数组
a = np.random.rand(10000, 10000)

# 使用 Dask 进行内存管理
dask_a = da.from_array(a, chunks=(1000, 1000))  # 分块处理数组
print(f"Dask 数组: \n{dask_a}")  # 输出 Dask 数组

# 计算平均值
mean_result = dask_a.mean().compute()  # 计算并释放中间结果
print(f"平均值: {mean_result}")  # 输出平均值
2.11.5 Dask集成案例

Dask 是一个并行计算库,可以与 NumPy 集成以处理大规模数据。通过 Dask,可以有效地管理内存,避免内存溢出。

  • Dask 基本概念:Dask 的基本概念和工作原理。
  • Dask 与 NumPy 集成:如何将 Dask 与 NumPy 集成。
  • 性能比较:Dask 与纯 NumPy 的性能比较。
Dask集成案例
Dask 基本概念
延迟计算
分块处理
Dask 与 NumPy 集成
创建 Dask 数组
执行计算
性能比较
计算时间
内存占用
import numpy as np
import dask.array as da
import time

# 创建一个大数组
np_a = np.random.rand(10000, 10000)

# 使用 Dask 创建分块数组
dask_a = da.from_array(np_a, chunks=(1000, 1000))

# 计算平均值(NumPy)
start_time = time.time()
np_mean = np_a.mean()
np_time = time.time() - start_time
print(f"使用 NumPy 计算平均值: {np_mean}, 用时: {np_time:.2f}秒")

# 计算平均值(Dask)
start_time = time.time()
dask_mean = dask_a.mean().compute()
dask_time = time.time() - start_time
print(f"使用 Dask 计算平均值: {dask_mean}, 用时: {dask_time:.2f}秒")

# 比较内存占用
import tracemalloc

tracemalloc.start()
np_a = np.random.rand(10000, 10000)
np_current, np_peak = tracemalloc.get_traced_memory()
tracemalloc.stop()

tracemalloc.start()
dask_a = da.from_array(np.random.rand(10000, 10000), chunks=(1000, 1000))
dask_mean = dask_a.mean().compute()
dask_current, dask_peak = tracemalloc.get_traced_memory()
tracemalloc.stop()

print(f"使用 NumPy 的内存峰值: {np_peak / 1024 / 1024:.2f} MB")
print(f"使用 Dask 的内存峰值: {dask_peak / 1024 / 1024:.2f} MB")
2.11.6 总结
  • 关键收获:理解视图与副本的创建条件,掌握深度拷贝机制,学会内存占用实时监控方法。
  • 最佳实践:合理使用视图和副本,及时释放不再使用的内存,避免内存泄漏。
  • 工具和库:使用 memory_profiler 进行内存监控,使用 Dask 进行大规模数据处理。

通过本文,我们深入探讨了 NumPy 中视图与副本的创建条件,副本的深度拷贝机制,内存占用的实时监控方法,内存泄漏的预防技巧,以及 Dask 与 NumPy 的集成案例。希望这些内容能帮助你在实际开发中更好地优化内存使用,提高代码性能,避免常见的内存陷阱。

2.11.7 参考文献
参考资料链接
《NumPy Beginner’s Guide》NumPy Beginner’s Guide
《Python for Data Analysis》Python for Data Analysis
NumPy 官方文档NumPy Reference
Dask 官方文档Dask Documentation
Stack OverflowHow to detect memory leaks in NumPy
MediumUnderstanding NumPy Views and Copies
Python Memory ManagementPython Memory Management
SciPy 官方文档SciPy Memory Efficiency
WikipediaMemory Leaks
《高性能Python》High Performance Python
《Python数据科学手册》Python Data Science Handbook

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


http://www.kler.cn/a/530113.html

相关文章:

  • 安卓(android)实现注册界面【Android移动开发基础案例教程(第2版)黑马程序员】
  • M|哪吒之魔童闹海
  • Python-基于PyQt5,wordcloud,pillow,numpy,os,sys等的智能词云生成器(最终版)
  • 猴子吃桃问题
  • JavaWeb入门-请求响应(Day3)
  • 个人笔记(很没营养,纯备忘录)
  • leetcode 2856. 删除数对后的最小数组长度
  • 【TypeScript】扩展:装饰器
  • 在Arm芯片苹果Mac系统上通过homebrew安装多版本mysql并解决各种报错,感谢deepseek帮助解决部分问题
  • Python 原子操作:使用 `atomic` 模块保证线程安全
  • web前端12--表单和表格
  • 科技快讯 | 领英“隐私风波”告一段落;华为余承东智驾 1345 公里返工,称智界 R7 打赢“鸡蛋保卫战”;谷歌翻译将增“提问”功能
  • 利用Spring Batch简化企业级批处理应用开发
  • 【漫话机器学习系列】075.隐含层(Hidden Layer)
  • Git如何避免推送.idea文件夹
  • 使用 vllm 搭建推理加速大模型服务
  • OpenAI 实战进阶教程 - 第二节:生成与解析结构化数据:从文本到表格
  • 想品客老师的第天:类
  • Java集合+并发(部分)
  • MultiResUNet学习笔记(2019 Neural Networks【SCI 1区】)
  • 用结构加法3ax+1预测第4点的分布
  • 掌握Spring MVC异常处理的艺术
  • ICLR 2025收录论文:为什么动作分块对于机器人灵活性至关重要?
  • makailio-alias_db模块详解
  • 蓝桥杯备考:六大排序算法
  • Hive重点面试题