在 python 中将列表存储在驱动器上的最快方法是什么?
What is the fastest approach of having a list stored on drive in python?
我在 python 中处理(真正的)大数据,对于每个输入,我需要计算一个数字,该数字稍后需要并且可能会更改。所以基本上我有一个整数向量(列表)。
当矢量的大小为O(10^9)
或更大时,无法将其装入内存。因此,显然,我需要将它保存到硬盘上的文件中。
所以我需要的是 class 和一对处理包含整数向量的文件的函数。
示例:
class FileVector:
def __init__(self, file_name)
def update(self, position, value)
def read(self, position)
为简单起见,请假设向量的大小是固定且已知的。还让文件在第一次使用 class 之前创建,我们关心的是如何 read/update 它 尽可能快。
所以问题 - 我应该选择哪种文件格式才能最大限度地提高 read/update 速度?或者,是否有任何已经实施的解决方案,最好是在标准库中?我试图找到一些但失败了。
我目前的想法:
- 单行上的每个数字,使用 readline 读取
- 单行数字,以空格分隔
- 可能是某种二进制格式?
请注意,update
和 read
都不能一次将整个向量加载到内存中。
10^9 是几千兆字节 - 仍然可以放入 RAM,即使在笔记本电脑上也是如此。 Python 像 NumPy 这样的库可以帮助解决这个问题 - 它们提供了专门的数组类型,具有较低的内存占用和一些不错的数学函数。
作为一个真正的大数据,我认为有数百TB或更多...像Hadoop这样的分布式框架通常用于处理这些TB卷的数据。
但是如果你只想要一个基于文件的数组,我会选择 mmap:
import struct
from mmap import mmap
class FileVector:
number_size = len(struct.pack("<i", 0))
def __init__(self, file_name, initial_size, default_value=0):
try:
self.f = open(file_name, "r+b")
except FileNotFoundError:
self.f = open(file_name, "w+b")
fill = self._number_to_bytes(default_value)
for i in range(initial_size):
self.f.write(fill)
self.f.flush()
self.m = mmap(self.f.fileno(), 0)
def close(self):
self.m.close()
self.f.close()
def update(self, position, value):
self.m.seek(self.number_size * position)
self.m.write(self._number_to_bytes(value))
def read(self, position):
self.m.seek(self.number_size * position)
return self._bytes_to_number(self.m.read(self.number_size))
def _number_to_bytes(self, n):
return struct.pack("<i", n)
def _bytes_to_number(self, b):
return struct.unpack("<i", b)[0]
fv = FileVector("data", 10**9)
print(fv.read(1000))
fv.update(1000, -42)
print(fv.read(1000)) # should return -42
但它当然不如 C/C++ 等中的速度快。 - 在我的笔记本上,它设法每秒进行 500 000 次更新或读取,但这可能超过了"normal"数据库可以实现。如果需要并行化,也可以在进程之间共享映射文件。
我在 python 中处理(真正的)大数据,对于每个输入,我需要计算一个数字,该数字稍后需要并且可能会更改。所以基本上我有一个整数向量(列表)。
当矢量的大小为O(10^9)
或更大时,无法将其装入内存。因此,显然,我需要将它保存到硬盘上的文件中。
所以我需要的是 class 和一对处理包含整数向量的文件的函数。
示例:
class FileVector:
def __init__(self, file_name)
def update(self, position, value)
def read(self, position)
为简单起见,请假设向量的大小是固定且已知的。还让文件在第一次使用 class 之前创建,我们关心的是如何 read/update 它 尽可能快。
所以问题 - 我应该选择哪种文件格式才能最大限度地提高 read/update 速度?或者,是否有任何已经实施的解决方案,最好是在标准库中?我试图找到一些但失败了。
我目前的想法:
- 单行上的每个数字,使用 readline 读取
- 单行数字,以空格分隔
- 可能是某种二进制格式?
请注意,update
和 read
都不能一次将整个向量加载到内存中。
10^9 是几千兆字节 - 仍然可以放入 RAM,即使在笔记本电脑上也是如此。 Python 像 NumPy 这样的库可以帮助解决这个问题 - 它们提供了专门的数组类型,具有较低的内存占用和一些不错的数学函数。
作为一个真正的大数据,我认为有数百TB或更多...像Hadoop这样的分布式框架通常用于处理这些TB卷的数据。
但是如果你只想要一个基于文件的数组,我会选择 mmap:
import struct
from mmap import mmap
class FileVector:
number_size = len(struct.pack("<i", 0))
def __init__(self, file_name, initial_size, default_value=0):
try:
self.f = open(file_name, "r+b")
except FileNotFoundError:
self.f = open(file_name, "w+b")
fill = self._number_to_bytes(default_value)
for i in range(initial_size):
self.f.write(fill)
self.f.flush()
self.m = mmap(self.f.fileno(), 0)
def close(self):
self.m.close()
self.f.close()
def update(self, position, value):
self.m.seek(self.number_size * position)
self.m.write(self._number_to_bytes(value))
def read(self, position):
self.m.seek(self.number_size * position)
return self._bytes_to_number(self.m.read(self.number_size))
def _number_to_bytes(self, n):
return struct.pack("<i", n)
def _bytes_to_number(self, b):
return struct.unpack("<i", b)[0]
fv = FileVector("data", 10**9)
print(fv.read(1000))
fv.update(1000, -42)
print(fv.read(1000)) # should return -42
但它当然不如 C/C++ 等中的速度快。 - 在我的笔记本上,它设法每秒进行 500 000 次更新或读取,但这可能超过了"normal"数据库可以实现。如果需要并行化,也可以在进程之间共享映射文件。