On Monday, 4 March 2013 at 04:22:01 UTC, bearophile wrote:
So this should be better:

http://codepad.org/B5b4uyBM

Bye,
bearophile

@bearophile: Thank you! Unfortunately the http://codepad.org/B5b4uyBM code runs a bit *slower* than the original D code. Yikes!

$  gdmd -O -inline -release -noboundscheck -m64 bear.d -ofdbear
$ time ./dbear
-1015380632 859379360 -367726792 -1548829944

real    2m36.971s
user    2m36.910s
sys 0m0.030s
$ time ./dbear
-1015380632 859379360 -367726792 -1548829944

real    2m34.425s
user    2m34.370s
sys 0m0.020s


@John Colvin: here is the disassembly of mmult() in both languages. Unfortunately I'm not literate in x86_64 assembly. Perhaps the problem is obvious to you? All I can really tell is that the g++ version is shorter.

The memory allocation, when timed separately (comment out mmult), is less than 60 msec for either version, so I don't think its a memory issue, although it could be caching issue since the matrix layouts are different.

### gdc version of mmult:

(gdb) disas /m  _D6matrix5mmultFAAiAAiAAiZv
Dump of assembler code for function _D6matrix5mmultFAAiAAiAAiZv:
56      void mmult(int[][] m1, int[][] m2, int[][] m3)
   0x00000000004352a0 <+0>:       push   %r15
   0x00000000004352a5 <+5>:       push   %r14
   0x00000000004352a7 <+7>:       push   %r13
   0x00000000004352a9 <+9>:       push   %r12
   0x00000000004352ab <+11>:      mov    %rdx,%r12
   0x00000000004352ae <+14>:      push   %rbp
   0x00000000004352af <+15>:      mov    %rsi,%rbp
   0x00000000004352b2 <+18>:      push   %rbx
   0x00000000004352b3 <+19>:      mov    %r9,-0x40(%rsp)
   0x00000000004352b8 <+24>:      mov    %rdi,-0x10(%rsp)
   0x00000000004352bd <+29>:      mov    %rsi,-0x8(%rsp)
   0x00000000004352c2 <+34>:      mov    %rdx,-0x20(%rsp)
   0x00000000004352c7 <+39>:      mov    %rcx,-0x18(%rsp)
   0x00000000004352cc <+44>:      mov    %r8,-0x30(%rsp)
   0x00000000004352d1 <+49>:      mov    %r9,-0x28(%rsp)
   0x00000000004352dc <+60>:      add    $0x1,%rdi
   0x00000000004352e0 <+64>:      lea    0x1(%rdx),%rdx
   0x00000000004352e4 <+68>:      mov    $0x1,%r15d
   0x00000000004352ea <+74>:      mov    %rdi,-0x38(%rsp)
   0x0000000000435315 <+117>:     add    $0x1,%r13
   0x0000000000435319 <+121>:     mov    $0x1,%r11d
   0x0000000000435330 <+144>:     mov    $0x1,%esi

57      {
58          foreach(int i, int[] m1i; m1)
   0x00000000004352a2 <+2>:       test   %rdi,%rdi
0x00000000004352d6 <+54>: je 0x4353aa <_D6matrix5mmultFAAiAAiAAiZv+266>
   0x00000000004352ef <+79>:      xor    %esi,%esi
   0x00000000004352f1 <+81>:      mov    %rsi,%rax
   0x00000000004352f4 <+84>:      shl    $0x4,%rax
   0x00000000004352f8 <+88>:      mov    0x8(%rbp,%rax,1),%r10
   0x0000000000435398 <+248>:     cmp    -0x38(%rsp),%rax
   0x000000000043539d <+253>:     mov    %r15,%rsi
0x00000000004353a0 <+256>: je 0x4353aa <_D6matrix5mmultFAAiAAiAAiZv+266>
   0x00000000004353a2 <+258>:     mov    %rax,%r15
0x00000000004353a5 <+261>: jmpq 0x4352f1 <_D6matrix5mmultFAAiAAiAAiZv+81>

59          {
60              foreach(int j, ref int m3ij; m3[i])
   0x00000000004352fd <+93>:      add    -0x40(%rsp),%rax
   0x0000000000435302 <+98>:      mov    (%rax),%r13
   0x0000000000435305 <+101>:     mov    0x8(%rax),%r14
   0x0000000000435309 <+105>:     test   %r13,%r13
0x000000000043530c <+108>: je 0x435394 <_D6matrix5mmultFAAiAAiAAiZv+244>
   0x0000000000435312 <+114>:     xor    %r9d,%r9d
   0x000000000043531f <+127>:     shl    $0x2,%r9
   0x0000000000435326 <+134>:     lea    (%r14,%r9,1),%rbx
   0x000000000043536c <+204>:     mov    %r11,%r9
   0x000000000043536f <+207>:     cmp    %r13,%rax
0x0000000000435372 <+210>: je 0x435394 <_D6matrix5mmultFAAiAAiAAiZv+244>
   0x0000000000435374 <+212>:     shl    $0x2,%r9
   0x000000000043537b <+219>:     mov    %rax,%r11
   0x000000000043537e <+222>:     lea    (%r14,%r9,1),%rbx
   0x000000000043538a <+234>:     mov    %r11,%r9
   0x000000000043538f <+239>:     cmp    %r13,%rax
0x0000000000435392 <+242>: jne 0x435374 <_D6matrix5mmultFAAiAAiAAiZv+212>
   0x0000000000435394 <+244>:     lea    0x1(%r15),%rax

61              {
62                  int val;
   0x0000000000435337 <+151>:     xor    %edi,%edi
0x0000000000435339 <+153>: jmp 0x435343 <_D6matrix5mmultFAAiAAiAAiZv+163>
   0x000000000043533b <+155>:     nopl   0x0(%rax,%rax,1)
   0x0000000000435388 <+232>:     xor    %edi,%edi

63                  foreach(int k, int[] m2k; m2)
   0x0000000000435323 <+131>:     test   %r12,%r12
0x000000000043532a <+138>: je 0x435384 <_D6matrix5mmultFAAiAAiAAiZv+228>
   0x000000000043532c <+140>:     nopl   0x0(%rax)
   0x0000000000435335 <+149>:     xor    %eax,%eax
   0x0000000000435340 <+160>:     mov    %r8,%rsi
   0x0000000000435343 <+163>:     mov    %rax,%r8
   0x000000000043534a <+170>:     shl    $0x4,%r8
   0x000000000043535e <+190>:     cmp    %rdx,%r8
   0x0000000000435361 <+193>:     mov    %rsi,%rax
0x0000000000435364 <+196>: jne 0x435340 <_D6matrix5mmultFAAiAAiAAiZv+160>
   0x0000000000435366 <+198>:     lea    0x1(%r11),%rax
   0x0000000000435378 <+216>:     test   %r12,%r12
0x0000000000435382 <+226>: jne 0x435330 <_D6matrix5mmultFAAiAAiAAiZv+144>
   0x0000000000435384 <+228>:     lea    0x1(%r11),%rax

64                  {
65                      val += m1i[k] * m2k[j];
   0x0000000000435346 <+166>:     mov    (%r10,%rax,4),%eax
   0x000000000043534e <+174>:     mov    0x8(%rcx,%r8,1),%r8
   0x0000000000435353 <+179>:     imul   (%r8,%r9,1),%eax
   0x0000000000435358 <+184>:     lea    0x1(%rsi),%r8
   0x000000000043535c <+188>:     add    %eax,%edi

66                  }
67                  m3ij = val;
   0x000000000043536a <+202>:     mov    %edi,(%rbx)
   0x000000000043538d <+237>:     mov    %edi,(%rbx)

68              }
69          }
70      }
   0x00000000004353aa <+266>:     pop    %rbx
   0x00000000004353ab <+267>:     pop    %rbp
   0x00000000004353ac <+268>:     pop    %r12
   0x00000000004353ae <+270>:     pop    %r13
   0x00000000004353b0 <+272>:     pop    %r14
   0x00000000004353b2 <+274>:     pop    %r15
   0x00000000004353b4 <+276>:     retq
   0x00000000004353b5:  data32 nopw %cs:0x0(%rax,%rax,1)

End of assembler dump.
(gdb)


### g++ version of mmult:

(gdb) disas /m mmult
Dump of assembler code for function mmult(int, int, int**, int**, int**):
36      int **mmult(int rows, int cols, int **m1, int **m2, int **m3) {
   0x0000000000400a10 <+0>:       push   %r14
   0x0000000000400a14 <+4>:       push   %r13
   0x0000000000400a16 <+6>:       mov    %r8,%r13
   0x0000000000400a19 <+9>:       push   %r12
   0x0000000000400a1b <+11>:      push   %rbp
   0x0000000000400a1c <+12>:      push   %rbx
   0x0000000000400a1d <+13>:      mov    %edi,%ebx
   0x0000000000400a21 <+17>:      lea    -0x1(%rsi),%eax
   0x0000000000400a24 <+20>:      mov    %rdx,%r12
   0x0000000000400a27 <+23>:      xor    %ebp,%ebp
   0x0000000000400a29 <+25>:      lea    0x4(,%rax,4),%rdi
   0x0000000000400a40 <+48>:      xor    %r9d,%r9d
   0x0000000000400a43 <+51>:      xor    %r11d,%r11d
   0x0000000000400a46 <+54>:      nopw   %cs:0x0(%rax,%rax,1)

37          int i, j, k, val;
38          for (i=0; i<rows; i++) {
   0x0000000000400a12 <+2>:       test   %edi,%edi
0x0000000000400a1f <+15>: jle 0x400a7e <mmult(int, int, int**, int**, int**)+110>
   0x0000000000400a7a <+106>:     cmp    %ebp,%ebx
0x0000000000400a7c <+108>: jg 0x400a31 <mmult(int, int, int**, int**, int**)+33>

39              for (j=0; j<cols; j++) {
   0x0000000000400a31 <+33>:      test   %esi,%esi
0x0000000000400a33 <+35>: jle 0x400a76 <mmult(int, int, int**, int**, int**)+102>
   0x0000000000400a35 <+37>:      mov    (%r12,%rbp,8),%r8
   0x0000000000400a39 <+41>:      mov    0x0(%r13,%rbp,8),%rdx
   0x0000000000400a3e <+46>:      xor    %eax,%eax
   0x0000000000400a71 <+97>:      cmp    %rdi,%rax
0x0000000000400a74 <+100>: jne 0x400a40 <mmult(int, int, int**, int**, int**)+48>
   0x0000000000400a76 <+102>:     add    $0x1,%rbp

40                  val = 0;
41                  for (k=0; k<cols; k++) {
   0x0000000000400a64 <+84>:      cmp    %r9d,%esi
0x0000000000400a67 <+87>: jg 0x400a50 <mmult(int, int, int**, int**, int**)+64>

42                      val += m1[i][k] * m2[k][j];
   0x0000000000400a50 <+64>:      mov    (%rcx,%r9,8),%r14
   0x0000000000400a54 <+68>:      mov    (%r8,%r9,4),%r10d
   0x0000000000400a58 <+72>:      add    $0x1,%r9
   0x0000000000400a5c <+76>:      imul   (%r14,%rax,1),%r10d
   0x0000000000400a61 <+81>:      add    %r10d,%r11d

43                  }
44                  m3[i][j] = val;
   0x0000000000400a69 <+89>:      mov    %r11d,(%rdx,%rax,1)
   0x0000000000400a6d <+93>:      add    $0x4,%rax

45              }
46          }
47          return(m3);
48      }
   0x0000000000400a7e <+110>:     pop    %rbx
   0x0000000000400a7f <+111>:     pop    %rbp
   0x0000000000400a80 <+112>:     pop    %r12
   0x0000000000400a82 <+114>:     mov    %r13,%rax
   0x0000000000400a85 <+117>:     pop    %r13
   0x0000000000400a87 <+119>:     pop    %r14
   0x0000000000400a89 <+121>:     retq

End of assembler dump.
(gdb)

Reply via email to