Mr.Wizard has shown how memory performance is affected. I wish to illustrate various aspects of timing performance.
First,
Developer`ToPackedArray@Table[]
takes about the same time as ConstantArray[]
:
v = Range@1*^6; (* all examples with Mr.Wizard's (packed) v *)
With[{copt = SystemOptions["CompileOptions"]},
Internal`WithLocalSettings[
SetSystemOptions["CompileOptions" -> {"TableCompileLength" -> Infinity}],
Benchmark[{ConstantArray[v, {#}] &, Developer`ToPackedArray@Table[v, {#}] &}, 2^# &],
SetSystemOptions[copt]]]
(*
{{{1, 0.0058}, {2, 0.012}, {4, 0.045}, {6, 0.324}, {8, 1.2742}},
{{1, 0.0058}, {2, 0.012}, {4, 0.0442}, {6, 0.31}, {8, 1.250}}}
*)
Second,
this is because Table[v, {n}]
is really fast, since it is only copying n
pointers:
With[{copt = SystemOptions["CompileOptions"]},
Internal`WithLocalSettings[
SetSystemOptions["CompileOptions" -> {"TableCompileLength" -> Infinity}],
Benchmark[{ConstantArray[v, {#}] &, Table[v, {#}] &}, 2^# &],
SetSystemOptions[copt]]]
(*
{{{1, 0.0058}, {2, 0.011}, {4, 0.043}, {6, 0.317}, {8, 1.4}},
{{1, 9.4*10^-7}, {2, 9.89*10^-7}, {3, 1.2*10^-6}, {5, 2.3*10^-6}, {8, 0.000016}, ...}}
*)
Third,
Table[v, {n}]
is about twice as slow as ConstantArray[v, {n}]
, if n
is greater than or equal to "TableCompileLength"
:
With[{copt = SystemOptions["CompileOptions"]},
Internal`WithLocalSettings[
SetSystemOptions["CompileOptions" -> {"TableCompileLength" -> 1}],
Benchmark[{ConstantArray[v, {#}] &, Table[v, {#}] &},
2^# &, {1, 2, 4, 6, 8},
TimeConstraint -> 20.],
SetSystemOptions[copt]]]
(*
{{{1, 0.0059}, {2, 0.012}, {4, 0.043}, {6, 0.312}, {8, 1.258}},
{{1, 0.013}, {2, 0.023}, {4, 0.086}, {6, 0.61}, {8, 3.}}}
*)
Fourth,
for I/O, there's no difference in read speed, but the write speed is a bit strange (to me). I put in some Developer`PackedArrayQ
calls and turn on unpacking warnings to make sure there wasn't something I was missing. I timed both random and systematic access, and the results were opposite for the completely packed p
and the top-level unpacked up
.
read[arrayfn_] := Module[{d, a},
a = arrayfn[];
d = Dimensions[a];
BlockRandom[
SeedRandom[0, Method -> "MersenneTwister"];
{AbsoluteTiming[
Do[a[[RandomInteger[{1, d[[1]]}], RandomInteger[{1, d[[2]]}]]], {10^4}];
Developer`PackedArrayQ@a],
AbsoluteTiming[ (* different offsets j*k in each row *)
Do[a[[j, j*k]], {k, 10^3}, {j, 10}]; Developer`PackedArrayQ@a]}
]
];
write[arrayfn_] := Module[{d, a},
a = arrayfn[];
d = Dimensions[a];
BlockRandom[
SeedRandom[0, Method -> "MersenneTwister"];
{AbsoluteTiming[ (* different offsets j*k in each row *)
Do[a[[RandomInteger[{1, d[[1]]}], RandomInteger[{1, d[[2]]}]]] = -1, {10^4}];
Developer`PackedArrayQ@a],
a = arrayfn[]; (* reset array *)
AbsoluteTiming[
Do[a[[j, j*k]] = -2, {k, 10^3}, {j, 10}];
Developer`PackedArrayQ@a]}
]
]
Tests:
On["Packing"] (* just to double check *)
read[ConstantArray[v, {50}] &] (* packed === p *)
read[Table[v, {50}] &] (* unpacked of packed === up *)
(*
{{0.043588, True}, {0.009283, True}}
{{0.043868, False}, {0.009309, False}}
*)
write[ConstantArray[v, {50}] &] (* packed *)
write[Table[v, {50}] &] (* unpacked of packed *)
(*
{{0.056558, True}, {0.261569, True}}
{{0.243272, False}, {0.037485, False}}
*)
Off["Packing"]
Why is the systematic overwriting of p
so slow? (It makes no difference if you switch the orders of the iterators j
, k
.) If you comment out the reset-array line, then the timings are as follows:
write[ConstantArray[v, {50}] &] (* packed *)
write[Table[v, {50}] &] (* unpacked of packed *)
(*
{{0.05759, True}, {0.014992, True}}
{{0.244438, False}, {0.014401, False}}
*)
They're both the same, and twice as fast as the fastest with the array reset. If I switch the order of the systematic and random writes, then the packed array timing for the random writes depends on whether the array is reset. Maybe I'm doing something wrong, or maybe it's worth a separate question. Note that there is no difference in read
if the array is reset; but there is a difference in speed between the random and systematic reads, which I guess is due to caching by the computer and not due to Mathematica.
ConstantArray[N@Range[5], 5]
. $\endgroup$ – march Jul 18 '16 at 15:39"TableCompileLength"
(e.g. viaSetSystemOptions["CompileOptions" -> {"TableCompileLength" -> 2}]
) will forceTable[]
to generate a packed array. $\endgroup$ – J. M.'s ennui♦ Jul 18 '16 at 15:45