1
$\begingroup$

I was calculating the elements of a matrix like this:

Q = Table[Table[, S], S];
For[i = 1, i <= S, i++,
  For[j = 1, j <= S, j++,
    Q[[i, j]] =  (* Numerical calculation that depends on both `i` and `j`*);
    ] (* End For *);
  ] (* End For *) ;

Then I tried this:

Q = Table[Table[, S], S]; (* Probably this is no longer needed *)
Q = ParallelTable[
(* Numerical calculation that depends on both `i` and `j`*)   
,
   {i, 1, S}, {j, 1, S}];

In this way, I was able to reduce elapsed time (AbsoluteTiming) in a 50%, approximately. However, the computing time still remains unacceptably long for high values of S (the order of the square matrix Q).

What else can I try?

$\endgroup$
  • 2
    $\begingroup$ You could try to Compile your expression for Q[[i,j]]. If you need more detailed suggestions, consider adding code for your calculations, as it is difficult to help when we don't know more about what you're trying to do $\endgroup$ – Lukas Lang Sep 25 '17 at 15:43
  • 3
    $\begingroup$ The bottleneck is likely not in the looping construct, but the calculation of individual elements. That means that it's impossible to say much without knowing what you are calculating. For readability and reliability, consider Do instead of For when Table doesn't work. You can safely forget about For for this kind of use. If you use Table, use two iterators instead of nesting. $\endgroup$ – Szabolcs Sep 25 '17 at 15:52
  • 1
    $\begingroup$ This is mostly unanswerable unless you provide the expression for evaluating the matrix elements. I'll release the hold as soon as you edit your question. $\endgroup$ – J. M.'s technical difficulties Sep 26 '17 at 3:05
2
$\begingroup$

Here is a few tips on tuning lists. Consider the function f[x_]:=x^2 to be computed 10^6 times and comparing the time of each method:

Clear[f]
list = Table[RandomReal[{0, 10}], {i, 1, 10^6}];
sz = Length[list];
list2 = Table[0, {sz}];

f[x_] := x^2;

t1 = AbsoluteTiming[Map[f, list]];
Print["time Map = ", t1[[1]]];
t2 = AbsoluteTiming[f /@ list];
Print["time /@ = ", t2[[1]]];
t3 = AbsoluteTiming[f[#] &@list];
Print["time f[#]&@ = ", t3[[1]]];
t4 = AbsoluteTiming[Table[f[list[[i]]], {i, 1, sz}]];
Print["time Table = ", t4[[1]]];
t5 = AbsoluteTiming[Do[list2[[i]] = f[list[[i]]], {i, 1, sz}]];
Print["time Do = ", t5[[1]]];
t6 = AbsoluteTiming[
   For[i = 1, i <= sz, i++, list2[[i]] = f[list[[i]]]]];
Print["time For = ", t6[[1]]];



(*  time Map = 0.648596
    time /@ = 0.646969
    time f[#]&@ = 0.00440807
    time Table = 1.23878
    time Do = 1.96579
    time For = 2.54599*)

EDIT

Things get's faster when Compile is used:

Clear[f]
list = Table[RandomReal[{0, 10}], {i, 1, 10^6}];
sz = Length[list];
list2 = Table[0, {sz}];

f = Compile[{{x, _Real}}, x^2];
t1 = AbsoluteTiming[Map[f, list]];
Print["time Map = ", t1[[1]]];
t2 = AbsoluteTiming[f /@ list];
Print["time /@ = ", t2[[1]]];
t3 = AbsoluteTiming[f &@list];
Print["time f&@ = ", t3[[1]]];
t7 = AbsoluteTiming[Function[#^2] /@ list];
Print["Function[#^2]/@list= ", t7[[1]]];
t4 = AbsoluteTiming[Table[f[list[[i]]], {i, 1, sz}]];
Print["time Table = ", t4[[1]]];
t5 = AbsoluteTiming[Do[list2[[i]] = f[list[[i]]], {i, 1, sz}]];
Print["time Do = ", t5[[1]]];
t6 = AbsoluteTiming[
   For[i = 1, i <= sz, i++, list2[[i]] = f[list[[i]]]]];
Print["time For = ", t6[[1]]];

(*time Map = 0.0258033
time /@ = 0.0270923
time f&@ = 2.11302*10^-6
Function[#^2]/@list= 0.0275185
time Table = 0.163228
time Do = 1.55715
time For = 2.12429*)
| improve this answer | |
$\endgroup$
  • $\begingroup$ Could you explain why f[#] &@list is faster than Map[f, list]? I thought there were the same, as f @ list (I don't have MMA at hand right now to check). $\endgroup$ – anderstood Sep 26 '17 at 3:11
  • $\begingroup$ @understood I don't know for sure why it is faster, but it could be because f[#] &@list can directly accept a list without using Map, and this is more efficient. $\endgroup$ – Diogo Sep 26 '17 at 16:34
  • 1
    $\begingroup$ @anderstood Yes, f[#]& @ list is a more cumbersome, but very common, way of doing f @ list. As for speed, if list is a packed array, then vectorizable operations (e.g., Sin, Power, etc) that rely on packed array listability will be much faster than using Map, even if Map is compiled. See What is a Mathematica packed array?. $\endgroup$ – Carl Woll Sep 27 '17 at 4:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.