Использование памяти профилирования в Mathematica
Есть ли способ профилировать использование памяти mathkernel (вплоть до отдельных переменных), кроме как заплатить $$$ за их плагин Eclipse (математический workbench, iirc)?
В настоящий момент я завершаю выполнение программы, которая занимает несколько ГБ оперативной памяти, но единственные вещи, которые хранятся, должны быть не более 50 МБ данных, но mathkernel.exe имеет тенденцию удерживаться на ~ 1,5 ГБ (в основном, столько же как это даст Windows). Есть ли лучший способ обойти это, кроме сохранения необходимых мне данных и выхода из ядра каждый раз?
EDIT: я только что узнал о функции ByteCount (которая показывает некоторые тревожные результаты по базовым типам данных, но это помимо точки), но даже сумма по всем моим переменным нигде не приближается к сумме, принятой математическим выражением. Что дает?
Ответы
Ответ 1
Одна вещь, которую многие пользователи не понимают, заключается в том, что для хранения всех ваших входов и выходов в In
требуется память. Out
, независимо от того, присвоить ли вы переменную переменную. Out
также псевдонимы как %
, где %
- это предыдущий вывод, %%
является вторым по счету и т.д. %123
эквивалентно Out[123]
.
Если у вас нет привычки использовать %
или используйте его только на нескольких уровнях, установите $HistoryLength
до 0 или небольшое положительное целое число, чтобы сохранить только последние (или нет) выходы в Out
.
Вы также можете посмотреть функции MaxMemoryUsed
и MemoryInUse
.
Конечно, проблема $HistoryLength
может быть или не быть вашей проблемой, но вы не поделились тем, что ваша фактическая оценка.
Если вы сможете опубликовать его, возможно, кто-то сможет пролить больше света на то, почему он так интенсивен для памяти.
Ответ 2
Вот мое решение для профилирования использования памяти:
myByteCount[symbolName_String] :=
Replace[ToHeldExpression[symbolName],
Hold[x__] :>
If[MemberQ[Attributes[x], Protected | ReadProtected],
Sequence @@ {}, {ByteCount[
Through[{OwnValues, DownValues, UpValues, SubValues,
DefaultValues, FormatValues, NValues}[[email protected],
Sort -> False]]], symbolName}]];
With[{listing = myByteCount /@ Names[]},
Labeled[Grid[[email protected][Sort[listing], -100], Frame -> True,
Alignment -> Left],
Column[{Style[
"ByteCount for symbols without attributes Protected and \
ReadProtected in all contexts", 16, FontFamily -> "Times"],
Style[[email protected]{"Total: ", Total[listing[[All, 1]]], " bytes for ",
Length[listing], " symbols"}, Bold]}, Center, 1.5], Top]]
Оценка выше дает следующую таблицу:
![screenshot]()
Ответ 3
Майкл Пилат answer является хорошим, а MemoryInUse
и MaxMemoryUsed
, вероятно, являются лучшими инструментами, которые у вас есть. ByteCount
редко бывает полезным, потому что то, что оно измеряет, может быть огромным завышенным, поскольку оно игнорирует общие подвыражения и часто игнорирует память, которая напрямую не доступна через функции Mathematica, которая часто является основным компонентом использования памяти.
Одна вещь, которую вы можете сделать в некоторых случаях, - это использовать функцию Share
, которая позволяет по возможности делиться подвыражениями. В некоторых случаях это может сэкономить вам десятки или даже сотни мегабайт. Вы можете сказать, насколько хорошо он работает, используя MemoryInUse
до и после использования Share
.
Кроме того, некоторые безобидные вещи могут заставить Mathematica использовать намного больше памяти, чем вы ожидаете. Смежные массивы машинных реалов (и только машинные реалы) могут быть выделены в виде так называемых "упакованных" массивов, в основном так, как они будут выделены C или Fortran. Однако, если у вас есть сочетание машинных реалов и других структур (включая символы) в массиве, все должно быть "boxed" , и массив становится массивом указателей, что может добавить много накладных расходов.
Ответ 4
Один из способов - автоматизировать перезапуск ядра, когда он выходит из памяти. Вы можете выполнить свой потребляющий память код в подчиненном ядре, в то время как основное ядро принимает результат вычисления и контролирует использование памяти.