2013-04-24 5 views
3

Я должен предоставить заказчику как автономный Matlab . Код включает серию вызовов функции, которая внутренне создает несколько массивов ячеек.Ошибка «Недостаточно памяти» для автономных приложений Matlab - фрагментация памяти

Проблема заключается в том, что ошибка с отсутствием памяти возникает, когда число вызовов этой функции увеличивается в ответ на увеличение загрузки пользователя. Я думаю, это фрагментация памяти низкого уровня, поскольку переменные рабочей области не зависят от числа циклов.

Как упоминалось, here, выход и перезапуск Matlab - единственное решение для этого типа ошибок с нехваткой памяти на данный момент.

Вопрос о том, как я могу реализовать такой механизм в автономном приложении для сохранения данных, выхода и перезагрузки в случае ошибки вне памяти (или когда вероятность того, что такая ошибка будет предсказана каким-то образом) ,

Есть ли какая-либо лучшая практика?

Спасибо.

ответ

2

Это немного сложный вопрос. Вместо того, чтобы искать перезагрузки, чтобы очистить ситуацию, не могли бы вы изменить код, чтобы разбить работу на куски, чтобы сделать ее более эффективной? Фрагментация в основном пропорциональна значению памяти ячейки и размерам элементов данных, и меньше, чем к общему использованию с течением времени. Если вы можете разбить большую часть работы на мелкие кусочки, выполненные последовательно, это может снизить «высокую отметку воды» вашего фрагментированного использования памяти. Вы также можете сэкономить на использовании памяти, используя «мухи» структуры данных, которые делятся своими значениями данных поддержки или иногда конвертируются в структуры на основе ячеек для ссылок на объекты или числовые коды. Можете ли вы поделиться с нами примером своего кода и структуры данных?

Теоретически вы можете получить чистый список, сохранив свое рабочее пространство и соответствующее состояние в файл мата и имея исполняемый файл запуска другого экземпляра с возможностью перезагрузки этого состояния и продолжения, а затем с исходным исполняемым файлом Выход. Но это будет довольно уродливо с точки зрения пользовательского опыта и вашей способности отлаживать его.

Другим вариантом является разгрузка кода высокой фрагментации на другой рабочий процесс, который может быть убит и перезапущен, а основной исполняемый процесс сохранится. Если у вас есть Parallel Computation Toolbox, который теперь можно скомпилировать в автономные исполняемые файлы Matlab, это будет довольно просто: открыть рабочий пул из одного или двух рабочих и запустить фрагментарный код внутри них, используя синхронные вызовы, периодически убивая рабочих и воспитывать новых. Рабочие - это независимые процессы, которые начинаются с нефрагментированных пространств памяти. Если у вас нет PCT, вы можете свернуть свое собственное, скомпилировав свое приложение в виде двух отдельных приложений - приложения-драйвера и рабочего приложения, - и чтобы основное приложение развернуло работника и контролировало его через IPC, передавая ваши данные взад и вперед как файлы MAT или потоки. Впрочем, это не очень весело.

Возможно, вы могли бы также нажать часть фрагментированного кода на уровень Java, который более грамотно обрабатывает структуры данных, подобные ячейкам.

Изменение кода, чтобы быть менее фрагментированным, в первую очередь, возможно, является более простым и легким подходом и приводит к менее сложному дизайну приложения. По моему опыту это часто возможно. Если вы делитесь некоторыми данными о структуре кода и данных, возможно, мы можем помочь.

+1

+1 хороший ответ, как всегда. FWIW, вот два исключенных исключения, связанные с ошибками вне памяти (идентификатор и сообщение): «MException (« MATLAB: nomem »,« Out of memory ». Введите HELP MEMORY для ваших опций.») 'И' MException ('MATLAB: pmaxsize', 'Максимальный размер переменной, разрешенный программой, превышен.') '. Возможно, можно ловить такие ошибки и предупредить пользователя о необходимости перезапуска MATLAB – Amro

+0

Спасибо. И хороший момент. Если это случается только иногда, вы можете уйти с этим и работать меньше. Но может быть немного больше работы, чем кажется, потому что в графическом интерфейсе эти ошибки обычно происходят внутри функции обратного вызова, а AFAIK не существует ни одного цикла или контекста событий «верхнего уровня», где вы могли бы поставить try/catch для Это. Каждый вызов обратного вызова HG фактически представляет собой собственный кадр стека верхнего уровня. Вам придется записывать логику в каждую функцию обратного вызова или автоматически переносить каждый обратный вызов в обработчик ошибок. (Это выполнимо, я видел, как коллега это сделал, но сложный.) –

+0

Хм, вы правы, это не так просто, как обертывание всего кода в блок try/catch: \ – Amro

2

Другой вариант - периодически проверять фрагментацию памяти с помощью функции chkmem.

Вы можете включить эту функцию, чтобы называться бесшумно вы закодировать каждую пару итераций, или использовать timer объект, чтобы он назвал каждые Х минут ...

Идея заключается в том, чтобы использовать thse недокументированные функции feature memstats и feature dumpmem, чтобы получить самые большие свободные блоки памяти, доступные в дополнение к самым большим в настоящее время выделенным переменным. Используя это, вы можете сделать предположение, если есть признак фрагментации памяти.

При обнаружении вы должны предупредить пользователя и проинструктировать о том, как сохранить текущий сеанс (экспортировать в MAT-файл), перезапустить приложение и восстановить сеанс после перезапуска.

+0

Мне это нравится; более возможно, чем обертывание всех обратных вызовов. Вам больше не нужно использовать 'feature memstats' или' dumpmem'. Зарегистрированная функция «memory» теперь обеспечивает программный, структурированный доступ к тем же данным. Намного приятнее работать. Вы также можете посмотреть на «lasterror», чтобы узнать, была ли вызвана ошибка вне памяти в другом месте; это глобально по столам вызовов. –

+0

Подождите, моя ошибка - 'memory' отображает только самый большой свободный блок; вам по-прежнему нужны «функции memstats», чтобы получить топ-10 или около того, что является полезным индикатором. Сожалею; мог бы поклясться, что теперь есть еще один аргумент с блочным списком. –

+0

@ AndrewJanke: да, конечно, нет необходимости в недокументированных материалах :) Хотя вы могли бы делать дополнительные проверки с помощью 'dumpmem', например, видеть, где DLL загружаются в виртуальном адресном пространстве, поскольку иногда вы можете извлечь выгоду из переустановки этих повреждающих DLL, которые появляются в середине больших смежных блоков памяти – Amro