Кеширование данных в Mathematica - PullRequest
2 голосов
/ 29 июня 2010

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

myDataset = Module[{fname, data}, 
    fname = "cached-data.mx";
    If[FileExistsQ[fname], 
        Get[fname],
        data = Evaluate[timeConsumingOperation[]];
        Put[data, fname];
        data]
];

timeConsumingOperation[]:=Module[{},
    (* lot of work here *)
    {"data"}
];

Однако вместо записи длинного набора данных в файл команда Put записывает только одну строку: «timeConsumingOperation []», даже если я обертываю его с помощью Evaluate, как описано выше. (По правде говоря, это поведение не согласовано, иногда набор данных записывается, иногда нет.)

Как вы кешируете свои данные?

Ответы [ 2 ]

8 голосов
/ 29 июня 2010

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

f[arg1_, arg2_] := f[arg1, arg2] = someExpensiveThing[arg1, arg2]

Обратите внимание, что SetDelayed (:=) связывается выше Set (=), поэтому подразумеваемый порядокоценки следующие, но на самом деле вам не нужны парены:

f[arg1_, arg2_] := ( f[arg1, arg2] = someExpensiveThing[arg1, arg2])

Таким образом, при первой оценке f[1,2] оценивается RHS с задержкой оценки, в результате чего вычисляется результирующее значение исохраненный как OwnValue из f[1,2] с Set.

@ rcollyer также прав в том, что вам не нужно использовать пустые скобки, если у вас нет аргументов, вы можете так же легко написать:

g := g = someExpensiveThing[...]

Их использование не вредно.

1 голос
/ 29 июня 2010

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

f[x_Integers]:= x

, который не будет ничего соответствовать.Вместо этого я имел в виду

f[x_Integer]:=x

В вашем случае, однако, у вас нет шаблона для сопоставления: timeConsumingOperation[].

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

Теперь SetDelayed (:=) автоматически вызывает пересчет переменной всякий раз, когда она используется, и, поскольку вам не требуется передавать какие-либо параметры, квадратные скобки не нужны.Важным моментом здесь является то, что timeConsumingOperation может быть объявлено, как написано, до myDataset, потому что SetDelayed приведет к тому, что он не будет выполнен, пока не будет использован.

В общем, ваша методология кэширования выглядит именно так, как я бы поступил.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...