Memory leaks IPython.parallel模块内存泄漏?
我正在使用IPython.parallel来处理集群上的大量数据。我运行的远程功能如下所示:Memory leaks IPython.parallel模块内存泄漏?,memory-leaks,parallel-processing,ipython,Memory Leaks,Parallel Processing,Ipython,我正在使用IPython.parallel来处理集群上的大量数据。我运行的远程功能如下所示: def evalPoint(point, theta): # do some complex calculation return (cost, grad) 此函数将调用以下函数: def eval(theta, client, lview, data): async_results = [] for point in data: # evaluate
def evalPoint(point, theta):
# do some complex calculation
return (cost, grad)
此函数将调用以下函数:
def eval(theta, client, lview, data):
async_results = []
for point in data:
# evaluate current data point
ar = lview.apply_async(evalPoint, point, theta)
async_results.append(ar)
# wait for all results to come back
client.wait(async_results)
# and retrieve their values
values = [ar.get() for ar in async_results]
# unzip data from original tuple
totalCost, totalGrad = zip(*values)
avgGrad = np.mean(totalGrad, axis=0)
avgCost = np.mean(totalCost, axis=0)
return (avgCost, avgGrad)
如果我运行代码:
client = Client(profile="ssh")
client[:].execute("import numpy as np")
lview = client.load_balanced_view()
for i in xrange(100):
eval(theta, client, lview, data)
内存使用量一直在增长,直到最终耗尽(76GB内存)。我简化了evalPoint
以确保它不是罪魁祸首
eval
的第一部分是从IPython关于如何使用负载平衡器的文档中复制的。第二部分(解压和平均)相当简单,所以我认为这不是内存泄漏的原因。此外,我还尝试在eval
中手动删除对象,并调用gc.collect()
,但没有成功
我希望有IPython.parallel经验的人能指出一些明显的错误,或者能够确认这实际上是内存泄漏
另外一些事实:
- 我正在Ubuntu 11.10上使用Python 2.7.2
- 我使用的是IPython版本0.12
- 我的引擎运行在服务器1-3上,客户端和集线器运行在服务器1上。如果我把所有的东西都放在服务器1上,我会得到类似的结果
- 我发现的唯一一件类似于IPython内存泄漏的事情与
有关,我相信这在这个版本的IPython中已经修复(另外,我没有使用%run
)%run
File "/usr/local/lib/python2.7/dist-packages/IPython/parallel/controller/hub.py", line 1076, in purge_results
self.db.drop_matching_records(dict(completed={'$ne':None}))
File "/usr/local/lib/python2.7/dist-packages/IPython/parallel/controller/sqlitedb.py", line 359, in drop_matching_records
expr,args = self._render_expression(check)
File "/usr/local/lib/python2.7/dist-packages/IPython/parallel/controller/sqlitedb.py", line 296, in _render_expression
expr = "%s %s"%null_operators[op]
TypeError: not enough arguments for format string
所以,我想如果我使用DictDB,我可能会没事(今晚我要试着跑步)。我不确定是否仍会有一些内存消耗(我也会按照您的建议在客户端中进行清除)。是控制器进程在增长,还是客户端在增长,还是两者都在增长 控制器会记住所有请求和所有结果,因此将此信息存储在简单dict中的默认行为将导致持续增长。使用db后端(sqlite或最好是mongodb,如果有的话)可以解决这个问题,或者可以使用
客户端。purge_results()
方法来指示控制器放弃任何/所有结果历史记录(如果您使用的是db历史记录,这将从db中删除它们)
客户机本身在其results
dict中缓存自己的所有结果,因此这也会随着时间的推移导致增长。不幸的是,这一个更难处理,因为引用可以向所有方向传播,并且不受控制器的db后端的影响
这是IPython中的一个示例,但现在,您应该能够通过删除客户端结果/元数据目录中的条目来手动清除引用,如果您的视图仍然存在,则它有自己的结果目录:
# ...
# and retrieve their values
values = [ar.get() for ar in async_results]
# clear references to the local cache of results:
for ar in async_results:
for msg_id in ar.msg_ids:
del lview.results[msg_id]
del client.results[msg_id]
del client.metadata[msg_id]
或者,您可以使用simpledict.clear()
清除整个客户端缓存:
旁注:
视图有自己的wait()方法,因此您根本不需要将客户机传递给函数。所有内容都应该可以通过视图访问,如果您确实需要客户端(例如清除缓存),您可以通过
视图获取。客户端
感谢您花时间回复!我没有足够的空间来正确地回答所有问题,所以我把其余的回答放在问题的底部。我昨天晚上能够跑完全程,所以只要我使用DictDB,我的问题就解决了。我猜MongoDB可能会有一个限制内存使用的选项,但这是另一个问题。我想补充一点:一个有趣的事情是DictDB对我的进程的运行速度比MongoDB或SQLite快得多。我猜这是由于进程完成的速度和簿记的开销造成的。谢谢,我修复了sqlite的打字错误。db后端的一部分要点是不需要清除结果。如果您仍然使用它,我建议您尽可能少地使用它。新设计的一部分优点是,速度慢的集线器无法降低执行速度,但只有在不总是阻塞集线器操作的情况下,这才是正确的。另外,请参见和。至少对于SQLiteDB,如果不清除,它会占用我所有的内存。感谢您提供MongoDB的信息。那么,从理论上讲,这是否意味着我应该能够运行Mongo而无需清除?
view.results.clear()
client.results.clear()
client.metadata.clear()