Thread Local Remember Tables - Maple Help

In Maple 17 remember tables are thread local by default.  When a procedure with a remember table is called by multiple threads, the remembered results are only available on the thread that created them.  This differs from previous versions of Maple where remember tables were shared between threads, thus changes to the table in one thread would effect other threads.

This change allows a procedure with a remember table that works when run on a single thread to continue to work when run in parallel, regardless of how the procedure uses its remember table.  In previous versions of Maple a procedure could manipulate its remember table in such away as to break the behavior of a parallel execution of the procedure.

The following procedures implement a sequence similar to Fibonacci, where each term is the sum of the previous two terms, however the user can specify the initial values.  A remember table is used to improve the performance of this procedure.  The initial values are stored in FibsHelper's remember table where they act as the termination condition for the recursion.

 > FibsHelper := proc (n::nonnegint)  option remember;  FibsHelper(n-1)+FibsHelper(n-2)   end proc;
 ${\mathrm{FibsHelper}}{:=}{\mathbf{proc}}\left({n}{::}{\mathrm{nonnegint}}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{option}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{remember}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{FibsHelper}}{}\left({n}{âˆ’}{1}\right){+}{\mathrm{FibsHelper}}{}\left({n}{âˆ’}{2}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}$ (1)

 > Fibs := proc (n::nonnegint, t1 := 1, t2 := 1)  subsop(4 = NULL, op(FibsHelper));  FibsHelper(0) := t1;  FibsHelper(1) := t2;  FibsHelper(n)  end proc;
 ${\mathrm{Fibs}}{:=}{\mathbf{proc}}\left({n}{::}{\mathrm{nonnegint}}{,}{\mathrm{t1}}{:=}{1}{,}{\mathrm{t2}}{:=}{1}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{subsop}}{}\left({4}{=}{\mathrm{NULL}}{,}{\mathrm{op}}{}\left({\mathrm{FibsHelper}}\right)\right){;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{FibsHelper}}{}\left({0}\right){:=}{\mathrm{t1}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{FibsHelper}}{}\left({1}\right){:=}{\mathrm{t2}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{FibsHelper}}{}\left({n}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}$ (2)

 > seq(Fibs(i), i = 0 .. 10);
 ${1}{,}{1}{,}{2}{,}{3}{,}{5}{,}{8}{,}{13}{,}{21}{,}{34}{,}{55}{,}{89}$ (3)

 > seq(Fibs(i, 2, 2), i = 0 .. 10);
 ${2}{,}{2}{,}{4}{,}{6}{,}{10}{,}{16}{,}{26}{,}{42}{,}{68}{,}{110}{,}{178}$ (4)



 > seq(Fibs(i, 2, 38), i = 0 .. 10);
 ${2}{,}{38}{,}{40}{,}{78}{,}{118}{,}{196}{,}{314}{,}{510}{,}{824}{,}{1334}{,}{2158}$ (5)

This works when run on a single thread, and in Maple 17, it works when run in parallel.

 > task := proc (n, t1, t2) local i; [seq(Fibs(i, t1, t2), i = 0 .. 10)] end proc;
 ${\mathrm{task}}{:=}{\mathbf{proc}}\left({n}{,}{\mathrm{t1}}{,}{\mathrm{t2}}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{local}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{i}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\left[{\mathrm{seq}}{}\left({\mathrm{Fibs}}{}\left({i}{,}{\mathrm{t1}}{,}{\mathrm{t2}}\right){,}{i}{=}{0}{..}{10}\right)\right]\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}$ (6)

 $\left[{1}{,}{1}{,}{2}{,}{3}{,}{5}{,}{8}{,}{13}{,}{21}{,}{34}{,}{55}{,}{89}\right]{,}\left[{2}{,}{2}{,}{4}{,}{6}{,}{10}{,}{16}{,}{26}{,}{42}{,}{68}{,}{110}{,}{178}\right]{,}\left[{2}{,}{38}{,}{40}{,}{78}{,}{118}{,}{196}{,}{314}{,}{510}{,}{824}{,}{1334}{,}{2158}\right]$ (7)

In previous versions of Maple, the parallel evaluation can fail.

A procedure with a shared remember table (Maple's previous behavior) can still be created in Maple 17 by specifying the shared option.  The following procedure will work when used in a single thread, but not in parallel.

 > SharedFibsHelper := proc (n::nonnegint)  options remember, shared;  SharedFibsHelper(n-1)+SharedFibsHelper(n-2)  end proc;
 ${\mathrm{SharedFibsHelper}}{:=}{\mathbf{proc}}\left({n}{::}{\mathrm{nonnegint}}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{option}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{remember}}{,}{\mathrm{shared}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{SharedFibsHelper}}{}\left({n}{âˆ’}{1}\right){+}{\mathrm{SharedFibsHelper}}{}\left({n}{âˆ’}{2}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}$ (8)

 > SharedFibs := proc (n::nonnegint, t1 := 1, t2 := 1)  subsop(4 = NULL, op(SharedFibsHelper));  SharedFibsHelper(0) := t1;  SharedFibsHelper(1) := t2;  SharedFibsHelper(n)  end proc;
 ${\mathrm{SharedFibs}}{:=}{\mathbf{proc}}\left({n}{::}{\mathrm{nonnegint}}{,}{\mathrm{t1}}{:=}{1}{,}{\mathrm{t2}}{:=}{1}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{subsop}}{}\left({4}{=}{\mathrm{NULL}}{,}{\mathrm{op}}{}\left({\mathrm{SharedFibsHelper}}\right)\right){;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{SharedFibsHelper}}{}\left({0}\right){:=}{\mathrm{t1}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{SharedFibsHelper}}{}\left({1}\right){:=}{\mathrm{t2}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{SharedFibsHelper}}{}\left({n}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}$ (9)

 > seq(SharedFibs(i), i = 0 .. 10);
 ${1}{,}{1}{,}{2}{,}{3}{,}{5}{,}{8}{,}{13}{,}{21}{,}{34}{,}{55}{,}{89}$ (10)
 > seq(SharedFibs(i, 2, 2), i = 0 .. 10);
 ${2}{,}{2}{,}{4}{,}{6}{,}{10}{,}{16}{,}{26}{,}{42}{,}{68}{,}{110}{,}{178}$ (11)
 > seq(SharedFibs(i, 2, 38), i = 0 .. 10);
 ${2}{,}{38}{,}{40}{,}{78}{,}{118}{,}{196}{,}{314}{,}{510}{,}{824}{,}{1334}{,}{2158}$ (12)

When SharedFibs is called in parallel, incorrect results may be computed.  Note that due to the nature of parallel execution, incorrect results may not occur on every run.

 > sharedTask := proc (n, t1, t2)  local i;  [seq(SharedFibs(i, t1, t2), i = 0 .. 10)]  end proc;
 ${\mathrm{sharedTask}}{:=}{\mathbf{proc}}\left({n}{,}{\mathrm{t1}}{,}{\mathrm{t2}}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{local}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{i}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\left[{\mathrm{seq}}{}\left({\mathrm{SharedFibs}}{}\left({i}{,}{\mathrm{t1}}{,}{\mathrm{t2}}\right){,}{i}{=}{0}{..}{10}\right)\right]\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}$ (13)
 $\left[{1}{,}{1}{,}{2}{,}{3}{,}{5}{,}{8}{,}{13}{,}{21}{,}{34}{,}{650}{,}{89}\right]{,}\left[{2}{,}{2}{,}{4}{,}{6}{,}{10}{,}{16}{,}{26}{,}{42}{,}{68}{,}{110}{,}{178}\right]{,}\left[{2}{,}{38}{,}{40}{,}{78}{,}{118}{,}{196}{,}{314}{,}{510}{,}{34}{,}{1334}{,}{2158}\right]$ (14)