在python中将浮动列表打包成字节的最快方法

2024-06-11 08:36:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个100k浮点的列表,我想把它转换成一个字节缓冲区。

buf = bytes()
for val in floatList:
   buf += struct.pack('f', val)
return buf

这相当慢。如何只使用标准的Python3.x库来提高速度。


Tags: in列表for标准return字节bytesval
3条回答

您可以使用ctypes,并使用与C中完全相同的双数组(或浮点数组),而不是将数据保存在列表中。这是一个相当低的水平,但如果你需要良好的表现,如果你的名单是一个固定规模的建议。

你可以创建一个等价的C double array[100]; 在Python中执行以下操作:

array = (ctypes.c_double * 100)()

ctypes.c_double * 100表达式生成一个Python类,用于一个双精度数组,100个项长。要将其连接到文件,只需使用buffer获取其内容:

>>> f = open("bla.dat", "wb")
>>> f.write(buffer(array))

如果您的数据已经在一个Python列表中,那么将其打包成一个双数组可能比调用struct要快,也可能不快,就像Agf接受的答案一样-我将把测量哪个更快作为家庭作业,但您需要的所有代码是:

>>> import ctypes
>>> array = (ctypes.c_double * len(floatlist))(*floatlist)

要将其视为字符串,只需执行以下操作:str(buffer(array))-这里的一个缺点是必须考虑浮点大小(float vs double)和依赖于CPU的浮点类型-struct模块可以为您处理这个问题。

最大的成功在于,使用float数组,您仍然可以将元素用作数字,方法是访问元素,就像访问一个普通的Python列表一样,同时使用buffer将元素用作平面内存区域。

告诉struct你有多少float。在我慢腾腾的笔记本电脑上,10万次漂浮大约需要1/100秒。

import random
import struct

floatlist = [random.random() for _ in range(10**5)]
buf = struct.pack('%sf' % len(floatlist), *floatlist)

有几个答案表明

import struct
buf = struct.pack(f'{len(floatlist)}f', *floatlist)

但是使用*不必要地将floatlist转换为元组,然后再将其传递给struct.pack。首先创建一个空缓冲区,然后使用slice赋值填充它,这样可以更快地避免这种情况:

import ctypes
buf = (ctypes.c_double * len(floatlist))()
buf[:] = floatlist

其他一些人可能可以使用的性能节省:

  • 只需再次执行赋值,就可以重用现有缓冲区,而不必创建新的缓冲区。
  • 可以通过指定给适当的切片来修改现有缓冲区的部分。

相关问题 更多 >