29

How to speed up Do loop in MMA 13.

We consider the following Benchmark test (4 kernels, i7, win10):

In MMA 13:

s = 5000;
Hmm = ConstantArray[0, {s, s}];

Do[Do[Hmm[[r, c]] = 1/(r + c - 1), {r, s}], {c, s}] // AbsoluteTiming

It takes 36.8516356 seconds.

But in Matlab 2021b

s = 5000;
H = zeros(s,s);

tic for c = 1:s for r = 1:s H(r,c) = 1/(r+c-1); end end toc

It only takes 0.114233 seconds......

Nearly 360 times slower than Matlab 2021b...

Update:

1.) If we use "Table"

s = 5000;
Hmm = ConstantArray[0, {s, s}];

AbsoluteTiming[ Table[Table[Hmm[[r, c]] = 1/(r + c - 1), {r, 1, s}], {c, 1, s}]]

It takes 36.6726 seconds...

2.) If we use "For"

AbsoluteTiming[
 For[c = 1, c <= s, c++, 
  For[r = 1, r <= s, r++, Hmm[[r, c]] = 1/(r + c - 1)]]]

It takes 46.7529 seconds...

3.) Test results from Matlab 2021b

enter image description here

4.) If we try "Compile" (https://mathematica.stackexchange.com/a/261329/54516)

Compile[{}, Module[{s, Hmm}, s = 5000;
     Hmm = Table[0., s, s];
     Do[Do[Hmm[[r, c]] = 1/(r + c - 1), {r, s}], {c, s}]; 
     Hmm]][]; // AbsoluteTiming

It takes 1.0638 seconds...

Nearly 10 times slower than Matlab 2021b...

5.) If we try another "Compile" (https://mathematica.stackexchange.com/a/261329/54516)

cf0 = With[{s = s}, 
    Compile[{}, Table[1/(r + c - 1), {r, 1, s}, {c, 1, s}], 
     CompilationTarget -> "C", RuntimeOptions -> "Speed"]][[-1]];

Hmm = cf0[]; // AbsoluteTiming

It takes 0.181941 seconds...

Nearly 2 times slower than Matlab 2021b...

Note that, for this special case: MATLAB and Mathematica are NOT equally fast.

6.) Why is tic/toc used (@xzczd's Question)?

Because e.g. "Use a pair of tic and toc calls to report the total time required for element-by-element matrix multiplication; use another pair to report the total runtime of your program." (https://www.mathworks.com/help/matlab/ref/toc.html)

Please check: https://www.mathworks.com/help/matlab/ref/toc.html

7.) How about julia 1.6.3 Do loops speed

@time Hmm=[1. /(r+c-1) for r=1:s,c=1:s];
    #  0.107591 seconds (85.06 k allocations: 195.439 MiB, 44.46% compilation time)

from @xzczd: (https://mathematica.stackexchange.com/a/261329/54516):

It takes 0.107591 seconds... @xzczd.

8.) The computational performance of the @chyanog's MMA code (@chyanog's comments https://mathematica.stackexchange.com/a/261329/54516)

s = 5000; 
 cf = With[{s = s}, 
   Compile[{{r, _Integer}}, Table[1/(r + c - 1), {c, 1, s}], 
    CompilationTarget -> "C", RuntimeOptions -> "Speed", 
    RuntimeAttributes -> {Listable}]]; 
 Hmm = cf[Range[s]]; // AbsoluteTiming

It takes 0.0717162 seconds... @chyanog.

Nearly 1.5 times faster than Matlab 2021b...

9.) "ParallelTable"

Based on the update 8.), now we test the ParallelTable :

cf = With[{s = s}, 
   Compile[{{r, _Integer}}, ParallelTable[1/(r + c - 1), {c, 1, s}], 
    CompilationTarget -> "C", RuntimeOptions -> "Speed", 
    RuntimeAttributes -> {Listable}]];

Hmm = cf[Range[s]]; // AbsoluteTiming

enter image description here

ABCDEMMM
  • 1,816
  • 1
  • 9
  • 17
  • Then what's the first-time cost of your MATLAB program? – xzczd Dec 29 '21 at 04:22
  • @xzczd in this post. – ABCDEMMM Dec 29 '21 at 04:24
  • Notice I'm compiling with -Ofast option of TDM-GCC, have you set the compiler properly? 2. By first-time cost I mean timing with a fresh kernel of MATLAB 3. s=5000 is small, what's the timing of larger s?
  • – xzczd Dec 29 '21 at 04:35
  • @xzczd if your conclusion is "Now MATLAB and Mathematica are equally fast." please show us the run time from MATLAB in your answer! It can be very helpful! – ABCDEMMM Dec 29 '21 at 04:37
  • I don't have access to MATLAB, but I've shown the timing of uncompiled Table and gfortran, which should be enough for comparison. – xzczd Dec 29 '21 at 04:40
  • For a fair comparison, you should include H = zeros(s,s) inside tic..toc, imo. – Michael E2 Dec 29 '21 at 04:44
  • @MichaelE2 in such case: >> untitled Elapsed time is 0.125228 seconds.

    untitled

    Elapsed time is 0.122755 seconds.

    untitled

    Elapsed time is 0.128294 seconds.

    – ABCDEMMM Dec 29 '21 at 04:46
  • Another hint: Do[Do[Hmm[[r, c]] = 1/(r + c - 1), {r, 1}], {c, 2}] // AbsoluteTiming. (Basically, preallocation was pointless.) – Michael E2 Dec 29 '21 at 04:47