Thursday, April 17, 2008

Initialize 2D Array

Three different ways to initialize a 2D array

char array[N][M];
and you want to initialize each member of that array to some character

//method 1, two loops
for(i=0;i < N;i++)
{

for(j=0;j < M;j++ )
{

a[i][j]='c';
}
}


//method2, one loop
char *p=a;
for(i=0;i < N*M;i++)
{

p[i]='d';
}


//method3, one line
memset(a,'e',N*M);

9 comments:

KBS said...

You need to use a different blogging service. Code looks horrible.

KBS said...
This comment has been removed by the author.
KBS said...

the nested loop method of setting multiarrays has submethods too

some ppl like to make the left/innermost indices change faster frequently (2 below), some like the make the right/outermost change faster (1 below)


example:

int array[n][m];

(1)
for(i=0; i < n; i++)
for(j=0; j < m; j++)
array[i][j] = 0;

(2)
for(j=0; j < m; j++)
for(i=0; i < n; i++)
array[i][j] = 0;



(2) is must worse than (1) ... try to think of why? They are equivalent at the C abstract level, but (1) is better at the actual machine level.

The other two methods (single loop and memset) you have listed in your original post are sometimes unable to help you in certain situations and when resorting to a nested loop construct, always use (1) for C.

In Fortran you would use (2).. i.e., make the rightmost indices change faster

That's why a lot of Fortran programmers who migrate to see are often caught using (2).. thus creating worse performing code.

Do you know why?

sridotc said...

[
(2) is must worse than (1) ... try to think of why?
]

obviously in c, rows in a matrix is contiguous in memory, so if you update them row by row, it is faster because of caching and block size

so I heard about this too, so fortan store them by column, then, thats why (2) is better for fortan

[
The other two methods (single loop and memset) you have listed in your original post are sometimes unable to help you in certain situations and when resorting to a nested loop construct
]

explain "resorting to a nested loop construct"

give me an example for this

KBS said...

You might want to initialize the array elements as s function of indices:

array[i][j][k] = f(i,j,k);

sridotc said...

what do you mean, then you would do something like the below

method 1
for ( i < N )
{
for ( j < M )
{
for ( k < O )
{
a[i][j][k] = f(i,j,k);
}
}
}

method2
char *p=a;
for ( n=0; n < N*M*O; n++)
{
k = n % O ;
j = n % M*O ;
i = n % N*M*O ;

p[n] = f(i,j,k);
}

method3 cannot be used here

KBS said...

Nobody would do that man.

The second method is probably slower with more assembly language code.

You are doing several divisions operations per loop. These operations are usually some of the slowest on a machine.

And it makes the code look retarted.

memset is ultra fast. Since you can't use it, you might as well use 3 nested loops instead of all that junk in the second method (junk = {extra divide and MOV operations} ).

And your code should be:

char *p = a;
for ( n = 0; n < N*M*O; n++)
p[n] = f( n/(M*O) , n/O , n%O );

sridotc said...

yea duhh

I was asking if thats what you meant

I know it will be slow

3 loops will be faster

KBS said...

for( )
for( )
for( )
for( )
if( )
goto found;

/* not found code goes here */

found:
/* found code goes here */