I really love the flexibility of Mathematica
: there are several ways to perform one task. However, to get the performance of the intense numeric calculation, it can cause some confuses. I wonder is it the real strength or the weakness of the language.
Example: Take a list of the first element in a matrix.
test1 = Transpose[{Range[10^8], Range[10^8]}];
The input list is Packed Array.
Developer`PackedArrayQ[test1]
True
For this simple task, there are many ways to do that. Now guess the performance of these commands:
(* test1 /. {a_, _} -> a; // Timing *) (* WARNING: May lock up your Mathematica! *)
First /@ test1; // Timing
test1[[All, 1]]; // Timing
Transpose[test1][[1]]; // Timing
First[Transpose[test1]]; // Timing
Take[Transpose[test1], 1]; // Timing
I think that, "Oh, the third one which uses only one function Part
. This one should be the fastest". The rule of thumb, is:
- Use lesser function will improve the speed
- Treat the data as the whole
- Use built-in function
- Use packed array, etc
- Avoid using Patterns for numerical calculation
So test1[[All, 1]]
should be the fastest. But no, I'm wrong.
Timing results:
The slowest solution is:
test1 /. {a_, _} -> a; // Timing
Don't run this, because Mathematica will be stuck. (I need to Abort the Evaluation). It's obvious because Pattern searching and replacement are expensive. Luckily I didn't often use this type of programming.
The next slow solution is:
First /@ test1; // Timing
{2.90625, Null}
Surprisingly, Part
is the next slow solution. I wonder why? This is the only case that uses one function Part
.
test1[[All, 1]]; // Timing
{1.21875, Null}
And the combinations of 2 functions approaches are faster. Transpose
and then Part
, First
and Transpose
, Take
and Transpose
.
Transpose[test1][[1]]; // Timing
First[Transpose[test1]]; // Timing
Take[Transpose[test1], 1]; // Timing
{0.765625, Null}
{0.734375, Null}
{0.609375, Null}
The main question here is, there are too many approaches to perform the same operation. And normally, I didn't know which approach is the most optimal way in terms of efficiency.
AbsoluteTiming
orRepeatedTiming
may be better tools to measure performance thanTiming
. $\endgroup$Part
to have the best performance here because it's the idiomatic way to do things and I'd expect internal optimizations to be in place for this. $\endgroup$