私は数百ギガバイトのデータをバイナリファイルに保存しています。私は無作為にいくつかの連続したレコードを何度も読んで、データのランダムサンプルを取っていきたいと思っています。Pythonの並列バッチでファイルを読む
データは多くのファイルに保存されています。メインファイルは特定の順序でデータを格納しないため、それぞれにソートされたインデックスファイルがあります。私の現在のコードは、多くのファイルがあることを除いて、このようなものです:
index = open("foo.index", 'rb')
data = open("foo", 'rb')
index_offset_format = 'Q'
index_offset_size = struct.calcsize(index_offset_format)
record_set = []
for _ in range(n_batches):
# Read `batch_size` offsets from the index - these are consecutive,
# so they can be read in one operation
index_offset_start = random.randint(0, N_RECORDS - batch_size)
index.seek(index_offset_start)
data_offsets = struct.iter_unpack(
index_offset_format,
index.read(index_offset_size * batch_size))
# Read actual records from data file. These are not consecutive
records = []
for offset in data_offsets:
data.seek(offset)
records.append(data.read(RECORD_SIZE))
record_set.append(records)
他のものはレコードで行われます。プロファイリングから、私はそのプログラムが大量のIOバインドされており、ほとんどの時間がindex.read
とdata.read
に費やされていることがわかります。これは、read
がブロックされているためです。インタプリタは、OSがディスクのデータを次のランダムなチャンクを要求する前にディスクから読み取るのを待っているため、ディスクアクセスパターンを最適化する機会はありません。だから:私は命令のバッチを渡すことができるいくつかのファイルAPIはありますか?何かのように:
def read_many(file, offsets, lengths):
'''
@param file: the file to read from
@param offsets: the offsets to seek to
@param lengths: the lengths of data to read
@return an iterable over the file contents at the requested offsets
'''
また、複数のファイルオブジェクトを開き、マルチスレッドを使用して複数の読み取りを要求すれば十分でしょうか?または、GILはそれが有用であるのを防ぐでしょうか?
関連性:https://stackoverflow.com/questions/29270818/why-is-a-python-i-o-bound-task-not-blocked-by-the-gil – ekhumoro
ファイルの最小サイズ、最大サイズ、平均サイズはどれくらいですか? – Apalala