TransWikia.com

Using block or module to free cache

Mathematica Asked by fpghost on April 15, 2021

I’m writing some code at the moment that schematically looks like:


(set initial conditions for some differential equation for given parameters (M,R,…))

M=1;
R=1: 

(NDSolve differential equation taking ~10mins or more to give solution dependent on some more paramaters (w,l,m); defining a memoized function)

Phi[w_?NumericQ,l_?IntegerQ,m_?IntegerQ]:=Phi[w,l,m]= "Interpolated Func result of  NDSolve taking 10mins to compute"

(For a given parameter set (w,l,m) compute a few things, such as coefficients and the (w,l,m) term in a sum, for which numerical differentiation ND[..] is needed, hence the necessity of memoizing this Phi to speed this step up)

A[w,l,m]:= "some calc dependent on the Phi";
B[w,l,m]:= "some calc dependent on the Phi"
termSum[w,l,m]:= "some calc dependent on the Phi and A,B"

(write termSum to file)

PutAppend[...]

(clear cache of the memoized Phi[w,l,m] interp func and the other variables like A[w,l,m])

Phi[1,2,3]:=.   (*unset*)

.
.
.
(after the rinse now repeat for a different (w,l,m))

Implemented by some 'do' or 'for' loop.

Some issues I’m considering:

1) Is there a way to use Block/Module say to allow me to better handle my caching of the variables (especially the huge memory hogs like the Phi that is a very large Interpolating Function)?

2) Also if I change my initial parameters M, R etc. I have to start all over again with setting initial conditions and so forth and functions that depend. Could I use Block/Module to incorporate this?

3) Is there a way to run some kind of initialization script in Mathematica that will set my constants, run my standard definitions etc. each time I load the notebook?

4) In a later calculation I will probably use the Phi,A,B for a given (w,l,m) all over again but for different values of ‘r’ along the range of the interpolating function. I’ve thought of saving to hard memory the actual interpolating functions of a given (w,l,m) but normal Save leads to 200MB files, and even DumpSave >20MB. Anything I could do about this or do I just have to recompute?

2 Answers

I appreciate that your code is probably too complex to post here, and that therefore we only have a sketch of what you’re doing, and therefore can’t give you absolutely precise advice. Here are some initial reactions.

  1. Yes, you can use Module to scope variables, but this is more about avoiding memory clashes than saving memory. You will find the information in this question useful.
  2. Why not make your other functions dependent on M and R? By the way, it is not good practice to use single-capital-letter names for functions in Mathematica, because some of them clash with built-in symbols. Also, it seems that definitions like A[w,l,m]:= aren't really functions because w, l and m aren't patterns. I think you mean A[w_,l_,m_]:=. If you use this version, you don't need to redefine the function every time you change m, assuming this is the same as M.
  3. Yes, you could either (a) put these definitions in a package (.m file) and load that using Needs["myPackage"]`, or (b) put the relevant defintions in initialization cells.
  4. Ajasja’s suggestion in comments to use one of the gzipped formats supported by Mathematica. The function $ExportFormats shows what formats are supported in your version and platform.

A couple of other suggestions:

  • Try Clear instead of Unset.
  • Try writing the results to individual files instead of using PutAppend. (You will need to use StringJoin and various other functions to automatically construct filenames.)

Answered by Verbeia on April 15, 2021

I know this is a very old question, but I recently wondered this myself and came up with this solution. My idea is to write a wrapper function the will cache function values for evaluations inside of the wrapper and then forget about them once it's done. You can do this with InheritedBlock:

SetAttributes[WithCachedValues, HoldAll];

WithCachedValues[functions : {__Symbol}, expr_] := Internal`InheritedBlock[functions,
    Scan[
        Function[{fun},
            Module[{outsideQ = True},
                DownValues[fun] = Prepend[ DownValues[fun],
                    HoldPattern[fun[args___] /; outsideQ] :> Block[{outsideQ = False},
                        With[{value = fun[args]},
                            Set[
                                fun[args],
                                value
                            ] /; value =!= Unevaluated[fun[args]]
                        ]
                    ]
                ]
            ],
            HoldFirst
        ],
        Unevaluated[functions]
    ];
    expr
];

To show how this works, define a dummy function like this:

ClearAll[f]
f[x_] := (Pause[1]; Print[x]; Sin[x]);

Calling f with WithCachedValues will only evaluate each argument of f once and then save the result for subsequent evaluations:

WithCachedValues[{f},
    {f[1], f[1], f[2], f[1], f[2]}
] // AbsoluteTiming

1

2

{2.00119, {Sin[1], Sin[1], Sin[2], Sin[1], Sin[2]}}

Once WithCachedValues is finished, the DownValues of f will be reset and the cached values will be cleared:

DownValues[f]

{HoldPattern[f[x_]] :> (Pause[1]; Print[x]; Sin[x])}

Edit

This function is now also available on the Wolfram Function Repository

Answered by Sjoerd Smit on April 15, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP