Передает ли переменная с большим объемом данных много памяти и времени в Mathematica? - PullRequest
15 голосов
/ 30 ноября 2011

Я пишу алгоритм построения суффиксного дерева в Mathematica на основе алгоритма Укконена.

Вопрос, который у меня возникает, состоит в том, передаст ли вся моя древовидная структура (которую я сохранил в списке) в функцию для поиска, будет стоить моей программе много памяти и времени, поскольку мне придется использоватьфункции несколько раз в алгоритме?

Например, у меня есть функция, которая ищет дочерние элементы определенного узла, и я использую функцию Select для поиска по всему дереву.

getChildren[parentID_] := Select[tree, #[[3]] == parentID &];

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

Ответы [ 2 ]

23 голосов
/ 30 ноября 2011

Нет, для передачи выражений не требуется дополнительная память.Как обычно в функциональных языках, объекты Mathematica неизменны : они не могут быть изменены, вместо этого создается новый объект, когда вы преобразуете их с помощью некоторой функции.Это также означает, что если вы не преобразуете их, они не копируются, независимо от того, сколько вы передаете их между функциями.


С точки зрения пользователя выражения Mathematica - это деревья, но яполагайте, что внутренне они хранятся как направленные ациклические графы , то есть одно и то же подвыражение может храниться только один раз в памяти, независимо от того, сколько раз оно появляется в полном выражении (см., например, страницу документа Share[]).

Вот пример для иллюстрации:

Сначала убедитесь, что In / Out не занимают дополнительную память:

In[1]:= $HistoryLength = 0;

Проверка использования памяти:

In[2]:= MemoryInUse[]
Out[2]= 13421756

Давайте создадим выражение, которое занимает заметный объем памяти:

In[3]:= s = f@Range[1000000];

In[4]:= MemoryInUse[]
Out[4]= 17430260

Теперь повторите это выражение сто раз ...

In[5]:= t = ConstantArray[s, 100];

... и обратите внимание, что использование памяти едва увеличивается:

In[6]:= MemoryInUse[]
Out[6]= 18264676

ByeCount[] вводит в заблуждение, поскольку не сообщает о реальной физической памятииспользуется, но память, которая будет использоваться 1036 * яf обычным подвыражениям не разрешено использовать одну и ту же память:

In[7]:= ByteCount[t]
Out[7]= 400018040

Интересный момент, на который следует обратить внимание: если вы удалите f[...] из s и сделаете оба s и t aпростой числовой массив, тогда это совместное использование памяти не произойдет, и использование памяти увеличится до ~ 400 МБ.


Если вы сделаете tree глобальной переменной или аргументом getChildren, это будетне имеет значения в использовании памяти.

4 голосов
/ 30 ноября 2011

В дополнение к ответам Szabolcs, если вам нужно изменить данные, этот вопрос может оказаться полезным при передаче по ссылке:

простой вопрос о передаче данных между функциями

...