chella said:
Is it a good practice to use 3D arrays in applications or I should use convert my
3D arrays to 1D arrays for efficiency.
On platforms with a data cache, it may be benficial to lay out your
array elements such that your loops traverse the elements in linear
order in memory, or at least do so more often. You may also want to
produce similar versions of a function to operate on both dynamic and
static arrays. If this is likely to be a concern, my personal
recommendation is this, supposing your array has dimensions m, n, p:
* define, dynamically allocate, or pass in a 1D array of size m*n*p
holding the elements
* define a "local" macro specific to that array taking three arguments
which performs the address calculation in the standard way (by "local"
macro, I mean #undef it at the end of the function, to avoid name
collisions later)
* get the algorithm working
* first, try rearranging loops to get better cache performance
* if this fails, fiddle with the macros until you get good performance
Here's an example of 2-operand destructive matrix addition with
fixed-size matrices:
#define M 20
#define N 50
#define P 100
void matrixAdd(int* arg_a, int* arg_b) {
#define a(i,j,k) (arg_a[(i)*N*P + (j)*P + (k)])
#define b(i,j,k) (arg_b[(i)*N*P + (j)*P + (k)])
int i,j,k;
for(i=0; i<M; i++)
for(j=0; j<N; j++)
for(k=0; k<P; k++)
a(i,j,k) += b(i,j,k);
#undef b
#undef a
}
Now with dynamic-sized:
void matrixAdd(int* arg_a, int* arg_b, int m, int n, int p) {
#define a(i,j,k) (arg_a[(i)*n*p + (j)*p + (k)])
#define b(i,j,k) (arg_b[(i)*n*p + (j)*p + (k)])
int i,j,k;
for(i=0; i<m; i++)
for(j=0; j<n; j++)
for(k=0; k<p; k++)
a(i,j,k) += b(i,j,k);
#undef b
#undef a
}
As macros go these are pretty safe - no reevaluation. Just watch out for
macro redefinitions and make sure your address calculations are actually
one-to-one.