【发布时间】:2019-12-11 14:39:16
【问题描述】:
我正在尝试使用 python 读取 > 20Gb 的大型文本文件。 文件包含 400 帧的原子位置,就我在此代码中的计算而言,每一帧都是独立的。理论上,我可以将工作拆分为 400 个任务,而无需任何沟通。每帧有 1000000 行,因此文件有 1000 000* 400 行文本。 我最初的方法是对工人池使用多处理:
def main():
""" main function
"""
filename=sys.argv[1]
nump = int(sys.argv[2])
f = open(filename)
s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
cursor = 0
framelocs=[]
start = time.time()
print (mp.cpu_count())
chunks = []
while True:
initial = s.find(b'ITEM: TIMESTEP', cursor)
if initial == -1:
break
cursor = initial + 14
final = s.find(b'ITEM: TIMESTEP', cursor)
framelocs.append([initial,final])
#readchunk(s[initial:final])
chunks.append(s[initial:final])
if final == -1:
break
这里基本上我正在寻找文件以查找框架的开头和结尾,以使用 python mmap 模块打开文件以避免将所有内容读入内存。
def readchunk(chunk):
start = time.time()
part = chunk.split(b'\n')
timestep= int(part[1])
print(timestep)
现在我想将文件块发送到工作人员池进行处理。 读取部分应该更复杂,但这些行将在稍后实现。
print('Seeking file took %8.6f'%(time.time()-start))
pool = mp.Pool(nump)
start = time.time()
results= pool.map(readchunk,chunks[0:16])
print('Reading file took %8.6f'%(time.time()-start))
如果我通过将 8 个块发送到 8 个内核来运行它,则需要 0.8 sc 才能读取。 然而 如果我通过将 16 个块发送到 16 个内核来运行它,则需要 1.7 sc。似乎并行化并没有加快速度。如果相关,我正在 Oak Ridge 的 Summit 超级计算机上运行它,我正在使用这个命令:
jsrun -n1 -c16 -a1 python -u ~/Developer/DipoleAnalyzer/AtomMan/readlargefile.py DW_SET6_NVT.lammpstrj 16
这应该创建 1 个 MPI 任务并将 16 个内核分配给 16 个线程。 我在这里想念什么吗? 有更好的方法吗?
【问题讨论】:
-
(1) 我不确定这是否真的可以避免复制块。最好只将块边界发送到子进程并让它们读取实际块。 (2) 一个简单的测试代码可能比实际工作的开销更大,因此时间可能不具有代表性。
-
并行化不会加快磁盘 I/O 到包含文件的单个物理驱动器的速度 - 并且使用多进程通常会自行引入相当多的开销。
标签: python python-multiprocessing large-files