You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NumPy ndarray.tofile与f.write性能差异及大数据场景性能疑问

为什么ndarray.tofile比f.write慢这么多?大数据集下表现如何?

哇,这个测试结果确实有点反直觉!先结合你给出的测试代码,拆解下为什么会出现这么大的性能差异,再聊聊大数据集下的表现~

先看你的测试数据

写入测试

  • ndarray.tofile(file): 10.668秒
timeit.timeit("a.tofile(f)", "import numpy as np; dt=np.dtype('B'); f=open('test.x','wb'); a=np.array(range(100),dt)")
  • file.write(ndarray.tobytes()): 0.316秒
timeit.timeit("f.write(a.tobytes())", "import numpy as np; dt=np.dtype('B'); f=open('test.x','wb'); a=np.array(range(100),dt)")

读取测试

  • np.array(list(f.read()), dt): 11.544秒
timeit.timeit("a=np.array(list(f.read()),dt)", "import numpy as np; dt=np.dtype('B'); f=open('test.x','rb');")
  • np.fromfile(f, dt): 11.544秒
timeit.timeit("a=np.fromfile(f,dt)", "import numpy as np; dt=np.dtype('B'); f=open('test.x','rb');")

一、小数据集下性能差异的核心原因

你的测试用的是仅100个字节的极小数组,这时候两种方法的「固定开销」占比完全不同:

  • ndarray.tofile() 每次调用时,会在C层面做一系列必要的准备工作:检查文件状态、处理跨平台字节序兼容、封装系统调用逻辑等。这些开销是固定的,当数据量极小时,固定开销直接主导了整个执行时间,导致看起来速度很慢。
  • f.write(a.tobytes()) 的逻辑是先把数组转成Python bytes 对象(小数据下这个转换几乎没开销),再调用文件的write方法。这里的主要开销是系统调用本身,而小数据下这个调用的开销远小于tofile的固定准备开销,所以整体速度快很多。

二、大数据集下的性能反转

当你处理MB级以上的大数据集时,情况会完全反过来,ndarray.tofile()会展现出明显的性能优势:

  • ndarray.tofile() 是直接在C层面操作数组的原始内存块,不需要额外的内存复制——它会把数组在内存中的二进制数据直接写入文件,跳过了Python层面的数据转换步骤,内存和时间效率都拉满。
  • 而a.tobytes() + f.write()的问题在于:tobytes()会先创建一个和数组大小完全相同的bytes对象,这相当于把数组的数据完整复制了一遍。当数据量很大时,这份内存复制的开销会急剧上升,不仅占用额外内存,还会拖慢整体写入速度。

三、关于读取测试的结果

你测试的两个读取方法耗时相同,同样是因为数据集太小:

  • np.array(list(f.read()), dt) 需要把文件读取的字节串转换成Python列表,再逐个元素转换成numpy数组,中间有大量Python层面的循环操作,开销很高。
  • np.fromfile(f, dt) 是C层面直接读取文件并解析成数组,理论上大数据下会快很多,但小数据下它的固定准备开销和手动转换的开销抵消了,所以看起来耗时一样。

总结

  • 小数据集下:f.write(a.tobytes()) 更快,因为tofile的固定开销占比太高
  • 大数据集下:ndarray.tofile() 性能更优,因为它避免了内存复制,直接操作原始内存

内容的提问来源于stack exchange,提问作者DarkMatterMatt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:34:46