Mathematica не хватает памяти - PullRequest
18 голосов
/ 28 октября 2009

Я пытаюсь запустить следующую программу, которая вычисляет корни полиномов степени до d с коэффициентами только +1 или -1, а затем сохраняет их в файлах.

d = 20; n = 18000; 
f[z_, i_] := Sum[(2 Mod[Floor[(i - 1)/2^k], 2] - 1) z^(d - k), {k, 0, d}];

Здесь f [z, i] дает многочлен от z со знаками плюс или минус, считая в двоичном виде. Скажем, d = 2, мы бы получили

f [z, 1] = -z 2 - z - 1
f [z, 2] = -z 2 - z + 1
f [z, 3] = -z 2 + z - 1
f [z, 4] = -z 2 + z + 1

DistributeDefinitions[d, n, f]

ParallelDo[ 
            Do[ 
                     root = N[Root[f[z, i], j]];
                     {a, b} = Round[n ({Re[root], Im[root]}/1.5 + 1)/2];
            {i, 1, 2^d}],
{j, 1, d}]

Я понимаю, что читать это, вероятно, не слишком приятно, но в любом случае оно относительно короткое. Я бы попытался сократить до соответствующих частей, но здесь я действительно понятия не имею, в чем проблема. Я вычисляю все корни f [z, i], а затем просто округляю их, чтобы они соответствовали точке сетки n на n, и сохраняю эти данные в различных файлах.

По какой-то причине использование памяти в Mathematica растет, пока не заполнит всю память (6 ГБ на этом компьютере); затем вычисление продолжается крайне медленно; почему это?

Я не уверен, что использует память здесь - мое единственное предположение было потоком файлов, использованным памятью, но это не так: я попытался добавить данные в файлы 2 ГБ, и для этого не было заметного использования памяти. Кажется, у Mathematica нет абсолютно никакой причины использовать здесь большие объемы памяти.

Для небольших значений d (например, 15), поведение следующее: у меня работает 4 ядра. Поскольку все они проходят через цикл ParallelDo (каждый из которых выполняет значение j за раз), использование памяти увеличивается, пока все они не закончат проходить этот цикл один раз. Затем в следующий раз, когда они пройдут этот цикл, использование памяти вообще не увеличится. Расчет в конце концов заканчивается, и все в порядке.

Также, что очень важно, после того, как вычисление останавливается, использование памяти не уменьшается. Если я начну другой расчет, произойдет следующее:

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

-Если предыдущий расчет прекратился, когда использование памяти не увеличивалось, оно больше не увеличивается.

Редактировать: Кажется, проблема связана с относительной сложностью f - изменение ее в более простой полином, кажется, решает проблему. Я подумал, что проблема может заключаться в том, что Mathematica запоминает f [z, i] для конкретных значений i, но устанавливает f [z, i]: =. просто после вычисления корня f [z, i] жалуется, что присвоение не существовало в первую очередь, и память все еще используется.

Это действительно довольно загадочно, так как f - единственное, что я могу себе представить, занимая память, но определение f во внутреннем цикле Do и очистка его каждый раз после вычисления корня не решает проблему.

1 Ответ

11 голосов
/ 29 октября 2009

Ой, это противно.

Что происходит, N будет выполнять кэширование результатов, чтобы ускорить будущие вычисления, если они вам понадобятся снова. Иногда это абсолютно то, что вы хотите, но иногда это просто разрушает мир. К счастью, у вас есть несколько вариантов. Одним из них является использование команды ClearSystemCache, которая выполняет то же, что и на банке. После того, как я немного запустил ваш непараллельный цикл (перед тем, как надоесть и прервать вычисления), MemoryInUse сообщил об использовании ~ 160 МБ. Использование ClearSystemCache снизило это до 14 МБ.

Единственное, на что вы должны обратить внимание, вместо программного вызова ClearSystemCache, - это использовать SetSystemOptions для изменения поведения кэширования. Вы должны взглянуть на SystemOptions["CacheOptions"], чтобы увидеть, каковы возможности.

РЕДАКТИРОВАТЬ: Не удивительно, что кэширование вызывает большие проблемы для более сложных выражений. Нужно где-то хранить копии этих выражений, а более сложные выражения требуют больше памяти.

...