Using Packed Arrays

Here is an example that shows how the use of packed arrays can significantly speed up certain computations. You will create a simple function for computing a two-dimensional lattice random walk.
Here are the compass directions. Note that NSEW is not packed:
In[]:=
NSEW={{0,1},{0,-1},{1,0},{-1,0}};​​Developer`PackedArrayQ[NSEW]
Out[]=
False
Here is the random walk function:
In[]:=
walk2D[t_]:=Accumulate[RandomChoice[NSEW,t]]
Compute how long a
10000000
-step walk takes:
In[]:=
RepeatedTiming[walk2D[
7
10
];]
Out[]=
{0.154873,Null}
Now, create a packed version of this code:
In[]:=
NSEWpacked=Developer`ToPackedArray[​​{{0,1},{0,-1},{1,0},{-1,0}}];​​Developer`PackedArrayQ[NSEWpacked]
Out[]=
True
In[]:=
walk2Dpacked[t_]:=Accumulate[RandomChoice[NSEWpacked,t]]
It is [claimed to be] roughly an order of magnitude speedup:
In[]:=
RepeatedTiming[walk2Dpacked[
7
10
];]
Out[]=
{0.154364,Null}
Is Accumulate automatically packing? Changing a 0 to 0. (integer to real) to prevent any possible automatic packing:
In[]:=
NSEWdefNotPacked={{0.,1},{0,-1},{1,0},{-1,0}};​​Developer`PackedArrayQ[NSEWdefNotPacked]
Out[]=
False
In[]:=
walk2DdefNotPacked[t_]:=Accumulate[RandomChoice[NSEWdefNotPacked,t]]
Test timings:
In[]:=
RepeatedTiming[walk2DdefNotPacked[
7
10
];]
Out[]=
{1.73329,Null}
In[]:=
Quit[]
In[]:=
NSEWmightGetPacked=​​{{0,1},{0,-1},{1,0},{-1,0}};​​Developer`PackedArrayQ[NSEWmightGetPacked]
Out[]=
False
In[]:=
walk2DmightGetPacked[t_]:=Accumulate[RandomChoice[NSEWmightGetPacked,t]]
In[]:=
RepeatedTiming[walk2DmightGetPacked[
7
10
];]
Out[]=
{0.186532,Null}