我认为这是一个相当简单的问题,但我似乎无法像我希望的那样让它发挥作用。我有~200~200 MB的文件,足以让我无法将它们全部加载到内存中。每个文件需要与每个其他文件一起处理(因此处理功能的约20000次操作)。我需要多次遍历文件,例如:
for i in xrange(len(file_list)-1): #go through each file
if i==0:
f = read(file_list[i]) #load in the first file
else:
f = g0 #we've already loaded in the next file once, don't re-load it
for j in xrange(i+1,len(file_list)): #go through each other file to get all unique pairs
g = read(file_list[i+j+1]) # takes 5 s
answer.append(processing_function(f,g)) # takes 10s
if j==0:
g = g0 # this will be "f" for the next iteration of the outer loop
外部循环只需要加载文件1,然后它可以将内部循环的第一次迭代中已加载的文件作为其下一个值。内部循环需要加载(len(file_list)-i)文件并处理它们。因为我无法在内存中保存~200个文件,并且没有简单的方法来分解文件列表(因为每个文件列表需要彼此配对一次)
是否有一种明显的方法可以并行化read()函数,使其至少读取下一个文件,即在执行processing_function(f_i,g_j)期间读取g_j + 1?我已经尝试了线程和多处理,并且我已经能够将读取卸载到不同的线程/进程中,但它并不能并行运行(即,execution_function()的执行开始一旦我得到ag,而未来的g_j正在后台加载)。我曾经设法挂起程序(使用多处理),或者只是在第一个(使用线程)上运行processing_function()之前将一堆文件加载到队列中。
我希望这很容易执行,我只是弄乱了一个细节。
这是我迄今为止尝试的内容(来自其他人建议的代码) - 似乎这样应该做我想要的,但就像我说的那样,似乎是file_worker QueuedFileReader()中的方法通过并将QUEUE_SIZE文件放入队列,然后将控制权交还给QueuedFileReader为生成器的循环。如果file_worker只是自己运行并且使用QueuedFileReader()的循环可以在队列中准备好单个文件以进行next()调用时,那将是完美的...
class QueuedFileReader():
def __init__(self,file_list,tmp_dir,QUEUE_SIZE):
self.queue =Queue.Queue(QUEUE_SIZE)
self.worker = threading.Thread(target=QueuedFileReader.file_worker,args=(self.queue,file_list,tmp_dir))
#self.queue = multiprocessing.Queue(QUEUE_SIZE)
#self.worker = multiprocessing.Process(target=QueuedFileReader.file_worker,args=(self.queue,file_list,tmp_dir))
self.worker.daemon=True
self.worker.start()
@staticmethod
def file_worker(queue,file_list,tmp_dir):
for i,f in enumerate(file_list):
done = False
while True and not done:
try:
print "attempting to read %s"%f_in
queue.put((i,f_in,files.read(f)))
print "successfully read in %s"%f
done = True
except Queue.Full:
pass
queue.put('done')
def __iter__(self):
return self
def next(self):
N = 0
while True:
try:
x = self.queue.get()
break
except Queue.Empty:
pass
if x == 'done': raise StopIteration
return x
def __del__(self):
self.worker.join()
来自:
for j,fnm,g in QueuedFileReader(flz[i+1:],tmp_dir,QUEUE_SIZE):
#the code that runs on object "f" from the outer loop and "g" that should be supplied off the top of the queue on each next() call to QueuedFileReader()