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

【教程】实测np.fromiter 和 np.array 的性能

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn]

如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~

目录

函数简介

np.fromiter

np.array

测试代码

实验结果

结果分析

实验总结

学长想说


函数简介

np.fromiter

np.fromiter 是 NumPy 提供的一个函数,用于从可迭代对象(如生成器、列表等)创建一个 NumPy 数组。它直接从可迭代对象中逐个读取数据,适合在数据量较大或数据生成过程中节省内存的场景。

优点:

  • 内存效率高:从可迭代对象中逐个读取数据而不是一次性加载所有数据,适合处理大数据量。
  • 速度较快:在特定情况下(尤其是数据量大时),由于从迭代器逐个读取数据,可能比 np.array 更快。

缺点:

  • 适用于从迭代器或生成器创建数组,对于已经存在的 Python 序列(如列表、元组)不具备明显优势。

np.array

np.array 是 NumPy 最常用的函数之一,用于将输入数据(如列表、元组、嵌套序列等)转换为 NumPy 数组。它会一次性读取输入数据并将其存储到内存中的连续块中,适合在数据已经加载到内存中的场景。

优点:

  • 通用性强:可以从各种序列(如列表、元组等)或其他数组对象创建 NumPy 数组。
  • 易于使用:语法简单,使用场景广泛。

缺点:

  • 对于非常大的数据,可能需要一次性加载到内存中,内存消耗较大。
  • 处理生成器或迭代器时,性能可能不如 np.fromiter

测试代码

import numpy as np
import time
import pandas as pd
import matplotlib.pyplot as plt# 测试数据生成函数
def generate_data(size):return range(size)  # 使用生成器来模拟大量数据# 测试 np.fromiter 的性能
def test_fromiter_int32(data):start_time = time.time()np.fromiter(data, dtype=np.int32)return time.time() - start_time# 测试 np.array 的性能(不计算 list 开销)
def test_array_no_list_overhead(data):data = list(data)  # 先将生成器转换为列表start_time = time.time()np.array(data, dtype=np.int32)  # 确保 dtype 为 int32return time.time() - start_time# 测试 np.array 的性能(计算 list 开销)
def test_array_with_list_overhead(data):start_time = time.time()data = list(data)  # 生成器转换为列表的时间也包含在内np.array(data, dtype=np.int32)  # 确保 dtype 为 int32return time.time() - start_time# 数据量从 10^1 到 10^9
data_sizes = [10**i for i in range(1, 8)]  # 从 10^1 到 10^7
results_comparison = []for size in data_sizes:data = generate_data(size)# np.fromiter 性能测试fromiter_time_int32 = test_fromiter_int32(data)# np.array 性能测试(不计算 list 开销)data = generate_data(size)  # 重新生成数据array_time_no_list_overhead = test_array_no_list_overhead(data)# np.array 性能测试(计算 list 开销)data = generate_data(size)  # 重新生成数据array_time_with_list_overhead = test_array_with_list_overhead(data)results_comparison.append((size, fromiter_time_int32, array_time_no_list_overhead, array_time_with_list_overhead))# 将结果显示为数据框
df_results_comparison = pd.DataFrame(results_comparison, columns=['Data Size', 'Fromiter Time (s)', 'Array Time without List Overhead (s)', 'Array Time with List Overhead (s)'
])# 绘制比较性能曲线
plt.figure(figsize=(10, 6))
plt.plot(df_results_comparison['Data Size'], df_results_comparison['Fromiter Time (s)'], marker='o', label='np.fromiter (int32)')
plt.plot(df_results_comparison['Data Size'], df_results_comparison['Array Time without List Overhead (s)'], marker='o', label='np.array without list overhead (int32)')
plt.plot(df_results_comparison['Data Size'], df_results_comparison['Array Time with List Overhead (s)'], marker='o', label='np.array with list overhead (int32)')
plt.xlabel('Data Size')
plt.ylabel('Time (s)')
plt.xscale('log')  # 使用对数刻度显示更大范围的数据
plt.yscale('log')  # 使用对数刻度显示时间差异
plt.title('Performance Comparison: np.fromiter vs np.array (dtype=int32)')
plt.legend()
plt.grid(True)
plt.show()

实验结果

结果分析

        从实验结果和图表中,我们可以观察到 np.fromiternp.array(不计算列表开销)和 np.array(计算列表开销)在不同数据量下的性能表现差异。以下是对实验结果的详细分析:

1. 小数据量 (10^110^3)

  • 性能差异较小:在数据量较小时(如 10^110^3),三种方法的执行时间差异非常小。此时,数据的处理开销可以忽略不计,所有方法的性能表现几乎相同。
  • np.fromiter 稍慢:在这些小数据量下,np.fromiter 的执行时间稍微比 np.array 长。这是因为 np.fromiter 需要逐个元素地从生成器中读取数据,而 np.array 直接操作列表(尤其是不计算列表开销时)。

2. 中等数据量 (10^410^5)

  • 开销开始显现:当数据量增加到 10^4 及以上时,np.array 方法开始表现出性能差异。特别是,当我们计算列表转换开销时,np.array 的执行时间开始显著增加。
  • np.fromiter 表现稳定np.fromiter 在中等数据量下表现相对稳定,时间随数据量线性增长,这表明其适合处理较大规模的数据。

3. 大数据量 (10^6 及以上)

  • np.array 的开销显著增加:对于 10^5 以上的数据量,包含列表转换的 np.array 方法的执行时间显著增加,表明当数据量很大时,列表转换开销成为一个显著的瓶颈。
  • np.fromiter 和不包含列表转换的 np.array 方法更优:在处理大数据时,这两种方法的时间相对较低,尤其是不计算列表开销的 np.array 方法,在大数据量下明显比计算列表开销的 np.array 更快。

实验总结

  • np.fromiter 的优势:当处理非常大的数据量且数据来源是生成器时,np.fromiter 表现得非常稳定且高效,适合处理大数据量。
  • np.array(不包含列表开销)适合已有数据结构:如果你已经有一个数据结构(如列表),并且需要将其转换为 NumPy 数组,那么不包含列表转换的 np.array 是最有效的选择。
  • 避免不必要的列表转换:在处理大数据时,避免将生成器不必要地转换为列表可以显著提高性能。因此,除非必要,尽量使用 np.fromiter 或直接将列表转换为数组,而不是将生成器转换为列表再转为数组。

学长想说

        还有一种情况,如果变量aaa已经是tensor了,那么使用aaa.numpy()比以上方法都高效

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • GCViT实战:使用GCViT实现图像分类任务(一)
  • Django+vue自动化测试平台(29)--测试平台集成playwright录制pytest文件执行
  • LeetCode 算法:杨辉三角 c++
  • Python——类和对象、继承和组合
  • 软考:软件设计师 — 17.程序设计语言与语言处理程序基础
  • IDEA: Html代码格式化
  • 【基础】Three.js中添加操作面板,GUI可视化调试(附案例代码)
  • Java-多线程IO工具类
  • MySQL入门学习-对系统数据库的常用查询
  • midwayjs 框架使用 rabbitmq 消息延迟
  • ES 根据条件删除文档
  • 【Python入门】第5节 数据容器
  • 分布式云扩展 AI 边缘算力,助力用户智能化创新
  • [Linux#47][网络] 网络协议 | TCP/IP模型 | 以太网通信
  • Apache RocketMQ 中文社区全新升级丨阿里云云原生 7 月产品月报
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【翻译】babel对TC39装饰器草案的实现
  • 10个最佳ES6特性 ES7与ES8的特性
  • Android开源项目规范总结
  • create-react-app项目添加less配置
  • es6要点
  • JS变量作用域
  • Rancher如何对接Ceph-RBD块存储
  • spring cloud gateway 源码解析(4)跨域问题处理
  • Spring Cloud中负载均衡器概览
  • spring security oauth2 password授权模式
  • Terraform入门 - 3. 变更基础设施
  • WinRAR存在严重的安全漏洞影响5亿用户
  • Zepto.js源码学习之二
  • 缓存与缓冲
  • 码农张的Bug人生 - 初来乍到
  • 为什么要用IPython/Jupyter?
  • 以太坊客户端Geth命令参数详解
  • Hibernate主键生成策略及选择
  • #Linux(Source Insight安装及工程建立)
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • (BFS)hdoj2377-Bus Pass
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (STM32笔记)九、RCC时钟树与时钟 第二部分
  • (初研) Sentence-embedding fine-tune notebook
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (贪心) LeetCode 45. 跳跃游戏 II
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)VC++中ondraw在什么时候调用的
  • (转)平衡树
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .net core 依赖注入的基本用发
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .Net多线程总结
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • .NET框架
  • .net中的Queue和Stack