现在,可能是50000年的某个东西非常大,导致了OOM,所以为了测试这个,我首先尝试:
file_list_chunks = list(divide_chunks(file_list_1,20000))[30000:]
如果在10000时失败,这将确认20k是否是块大小过大,或者如果在50000时再次失败,则代码有问题。。。
首先,你不需要
list
构造函数,在python中迭代而不是将整个列表生成到内存中要好得多。
file_list_chunks = list(divide_chunks(file_list_1,20000))
# becomes
file_list_chunks = divide_chunks(file_list_1,20000)
我认为您可能在这里误用了ThreadPool:
阻止任何其他任务提交到池中。完成所有任务后,工作进程将退出。
这读起来像
close
可能还有一些想法仍在运行,虽然我想这是安全的,但感觉有点不像pythonic,最好使用线程池的上下文管理器:
with ThreadPool(64) as pool:
results = pool.map(get_image_features,f)
# etc.
del
python中的s
aren't actually guaranteed to free memory
你应该收集
之后
加入/加入后:
with ThreadPool(..):
...
pool.join()
gc.collect()
锤子1
有一件事,我会考虑在这里做,而不是使用pandas数据帧和大列表是使用SQL数据库,您可以在本地使用
sqlite3
import sqlite3
conn = 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')")
这样,我们就不必处理大型列表对象或数据帧。
results = pool.map(get_image_features, zip(itertools.repeat(conn), f))
然后,在计算完成后,您可以从数据库中选择所有,选择您喜欢的格式。E、 g.使用
read_sql
.
锤子2
由于可以将start和end作为sys.args传递给python,因此可以对它们进行切片:
# main.py
# a for loop to iterate over this
subprocess.check_call(["python", "chunk.py", "0", "20000"])
# chunk.py a b
for count,f in enumerate(file_list_chunks):
if count < int(sys.argv[1]) or count > int(sys.argv[2]):
pass
# do stuff
这样,子进程将正确地清理python(因为进程将被终止,所以不可能有内存泄漏)。