Thread overview
static arrays.
Jan 30, 2007
Dave
Jan 31, 2007
Dave
Jan 31, 2007
torhu
Feb 01, 2007
Dave
January 30, 2007
Static ("rectangular") multi-dim arrays can perform pretty well - until you start passing them around as function parameters.

Two ways to get around that would be to wrap the arrays with a UDT passed byref, or use ptr params, with ptr's being much more intuitive for most applications of static arrays (IMO).

Attached is a matrix multiplication program ported to D from the original Shootout Delphi version (*).

The Delphi program has much cleaner syntax. For example, D pointer param dereferencing would be (*m1)[a][b] = (*m2)[c][d] * (*m3)[e][f] .

For me this begs the question: Why aren't D static arrays passed byref (**)?

(*) http://dada.perl.it/shootout/matrix_allsrc.html
(**) static array params cannot be 'inout'.

Thanks,

- Dave


January 31, 2007
Whoops - I should have made it clear that the programs perform roughly the same (D being about 10% faster), but only if the static matrices are passed byref (using pointer params) in D.

For Delphi, static arrays are passed byref.

Dave wrote:
> 
> Static ("rectangular") multi-dim arrays can perform pretty well - until you start passing them around as function parameters.
> 
> Two ways to get around that would be to wrap the arrays with a UDT passed byref, or use ptr params, with ptr's being much more intuitive for most applications of static arrays (IMO).
> 
> Attached is a matrix multiplication program ported to D from the original Shootout Delphi version (*).
> 
> The Delphi program has much cleaner syntax. For example, D pointer param dereferencing would be (*m1)[a][b] = (*m2)[c][d] * (*m3)[e][f] .
> 
> For me this begs the question: Why aren't D static arrays passed byref (**)?
> 
> (*) http://dada.perl.it/shootout/matrix_allsrc.html
> (**) static array params cannot be 'inout'.
> 
> Thanks,
> 
> - Dave
> 
> 
> ------------------------------------------------------------------------
> 
> module matrix;
> 
> import std.conv, std.stdio;
> 
> void main(char[][] args)
> {
>   int NUM = args.length > 1 ? toInt(args[1]) : 1;
>   TMatrix M1, M2, MM;
> 
>   mkmatrix(SIZE, SIZE, &M1);
>   mkmatrix(SIZE, SIZE, &M2);
>   for(int i = 0; i < NUM; i++)
>     mmult(SIZE, SIZE, &M1, &M2, &MM);
>   writefln(MM[0][0]," ",MM[2][3]," ",MM[3][2]," ",MM[4][4]);
> }
> 
> const SIZE = 30;
> 
> typedef int[SIZE][SIZE] TMatrix;
> 
> void mkmatrix(int rows, int cols, TMatrix* mx)
> {
>   int count = 1;
>   for(int R = 0; R < rows; R++)
>     for(int C = 0; C < cols; C++)
>     {
>       (*mx)[R][C] = count;
>       count++;
>     }
> }
> 
> void mmult(int rows, int cols, TMatrix* m1, TMatrix* m2, TMatrix* mm)
> {
>   for(int i = 0; i < rows; i++)
>     for(int j = 0; j < cols; j++)
>     {
>       int val = 0;
>       for(int k = 0; k < cols; k++)
>         val += (*m1)[i][k] * (*m2)[k][j];
>       (*mm)[i][j] = val;
>     }
> }
January 31, 2007
Dave wrote:
> Whoops - I should have made it clear that the programs perform roughly the same (D being about 10% faster), but only if the static matrices are passed byref (using pointer params) in D.
> 

I'm not sure what you mean.  Static arrays in D are passed as the address of the first element.  They are compatible with C arrays, at least in this respect.  So the speedup has to be caused by something else.
February 01, 2007
torhu wrote:
> Dave wrote:
>> Whoops - I should have made it clear that the programs perform roughly the same (D being about 10% faster), but only if the static matrices are passed byref (using pointer params) in D.
>>
> 
> I'm not sure what you mean.  Static arrays in D are passed as the address of the first element.  They are compatible with C arrays, at least in this respect.  So the speedup has to be caused by something else.

Thanks - you're right. I think I made a bad assumption based on a botched comparison.

Looking at it again, the following performs just as well. When I 'ported' it the first time from Delphi Pascal, I most likely had a typo in the original D code (?)

module matrix2;

import std.conv, std.stdio;

void main(char[][] args)
{
  int NUM = args.length > 1 ? toInt(args[1]) : 1;
  TMatrix M1, M2, MM;

  mkmatrix(SIZE, SIZE, M1);
  mkmatrix(SIZE, SIZE, M2);
  for(int i = 0; i < NUM; i++)
    mmult(SIZE, SIZE, M1, M2, MM);
  writefln(MM[0][0]," ",MM[2][3]," ",MM[3][2]," ",MM[4][4]);
}

const SIZE = 30;

typedef int[SIZE][SIZE] TMatrix;

void mkmatrix(int rows, int cols, TMatrix mx)
{
  int count = 1;
  for(int R = 0; R < rows; R++)
    for(int C = 0; C < cols; C++)
    {
      mx[R][C] = count;
      count++;
    }
}

void mmult(int rows, int cols, TMatrix m1, TMatrix m2, TMatrix mm)
{
  for(int i = 0; i < rows; i++)
    for(int j = 0; j < cols; j++)
    {
      int val = 0;
      for(int k = 0; k < cols; k++)
        val += m1[i][k] * m2[k][j];
      mm[i][j] = val;
    }
}