现在,可能是第50,000位的数据非常大,这导致了OOM,因此要对此进行测试,我将首先尝试:
file_list_chunks = list(divide_chunks(file_list_1,20000))[30000:]
如果它在10,000处失败,这将确认20k的块大小是否太大,或者如果再次在50,000处失败,则代码存在问题…
好的,进入代码…
首先,您不需要显式
list构造函数,在python中进行迭代比将整个列表生成到内存中要好得多。
file_list_chunks = list(divide_chunks(file_list_1,20000))# becomesfile_list_chunks = divide_chunks(file_list_1,20000)
我认为您可能在这里滥用ThreadPool:
阻止将更多任务提交给池。所有任务完成后,工作进程将退出。
这听起来像
close有些想法仍在运行,尽管我认为这是安全的,但感觉有点不符合Python风格,最好将上下文管理器用于ThreadPool:
with ThreadPool(64) as pool: results = pool.map(get_image_features,f) # etc.
实际上,不能保证
delpython中的显式s释放内存。
您应该 在 加入之后/之后使用:
with ThreadPool(..): ... pool.join()gc.collect()
您也可以尝试将其切成小块,例如10,000甚至更小!
锤子1
一件事,我会考虑在这里做,而不是使用pandas
Dataframes和大列表是使用SQL数据库,您可以使用sqlite3在本地进行此 *** 作:
import sqlite3conn = sqlite3.connect(':memory:', check_same_thread=False) # or, use a file e.g. 'image-features.db'
并使用上下文管理器:
with conn: conn.execute('''CREATE TABLE images (filename text, features text)''')with conn: # Insert a row of data conn.execute("INSERT INTO images VALUES ('my-image.png','feature1,feature2')")
这样,我们就不必处理大型列表对象或Dataframe。
您可以将连接传递给每个线程…您可能需要做些奇怪的事情:
results = pool.map(get_image_features, zip(itertools.repeat(conn), f))
然后,计算完成后,您可以从数据库中选择所有格式,并选择所需的格式。例如,使用read_sql。
锤子2
在这里使用一个子进程,而不是在python的“ shell out”的另一个实例中运行该子进程。
由于您可以将sys.args作为起点和终点传递给python,因此可以对它们进行切片:
# main.py# a for loop to iterate over thissubprocess.check_call(["python", "chunk.py", "0", "20000"])# chunk.py a bfor count,f in enumerate(file_list_chunks): if count < int(sys.argv[1]) or count > int(sys.argv[2]): pass # do stuff
这样,子进程将正确清理python(由于进程将终止,因此不会有内存泄漏)。
我敢打赌,Hammer
1是必经之路,感觉就像您要粘贴大量数据,并不必要地将其读取到python列表中,而使用sqlite3(或其他一些数据库)完全可以避免这种情况。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)