Я использую 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 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)
использование памяти продолжает расти до тех пор, пока у меня не закончится (76 ГБ памяти). Я упростил evalPoint
, чтобы ничего не делать, чтобы убедиться, что это не преступник.
Первая часть eval
была скопирована из документации IPython о том, как использовать балансировщик нагрузки. Вторая часть (распаковка и усреднение) довольно проста, поэтому я не думаю, что это ответственно за утечку памяти. Кроме того, я попытался вручную удалить объекты в eval
и безуспешно вызывать gc.collect()
.
Я надеялся, что кто-то, имеющий опыт работы с IPython.parallel, мог бы указать на очевидное, что я делаю неправильно, или смог бы подтвердить это на самом деле утечкой памяти.
Некоторые дополнительные факты:
- Я использую Python 2.7.2 в Ubuntu 11.10
- Я использую IPython версии 0.12
- У меня есть двигатели, работающие на серверах 1-3, а клиент и концентратор работают на сервере 1. Я получаю аналогичные результаты, если все храню только на сервере 1.
- Единственное, что я нашел похожим на утечку памяти для IPython, было связано с
%run
, который, я считаю, был исправлен в этой версии IPython (также я не использую %run
)
обновление
Кроме того, я попытался переключить ведение журнала из памяти на SQLiteDB, в случае, если это было проблемой, но все еще с той же проблемой.
ответ (1)
Потребление памяти определенно находится в контроллере (я мог убедиться в этом: (а) запустив клиент на другой машине и (б) просмотрев топ). Я не осознавал, что не SQLiteDB будет по-прежнему потреблять память, поэтому я не потрудился на очистку.
Если я использую DictDB и purge, я все равно вижу, как увеличивается потребление памяти, но гораздо медленнее. Это было около 2 ГБ для 20 вызовов eval ().
Если я использую MongoDB и purge, похоже, что mongod занимает около 4,5 ГБ памяти, а ipcluster - около 2,5 ГБ.
Если я использую SQLite и пытаюсь выполнить очистку, я получаю следующую ошибку:
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, у меня все будет хорошо (я собираюсь попробовать бегать сегодня вечером). Я не уверен, ожидается ли некоторое потребление памяти или нет (я также очищаю клиент, как вы предложили).