Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are the subscripts for three-dimensional arrays strictly defined?

Let's say I declare this:

int [a][b][c];

Does a stand for the level/page, b the row and c the column?

Or can it be anything I want it to be i.e. a stands for column, b stands for page, and c stands for row (since data is just data and a cube can be abstracted any way)?

like image 993
Brandon Tiqui Avatar asked Dec 09 '22 17:12

Brandon Tiqui


2 Answers

Anything you want in any order you want, the designations row and column are just convention. The layout in memory will be http://en.wikipedia.org/wiki/Row-major_order in C++, That part can't be changed.

How you iterate through the elements will have an impact on performance in many cases. You want to change the rightmost index in your innermost loop to move through memory sequentially.

like image 168
John Knoeller Avatar answered Jan 25 '23 23:01

John Knoeller


If you define:

int my_array[10][10][10];

One thing that's required is the meaning of the indices with respect to storage. my_array[1][2][3] is adjacent in memory to my_array[1][2][4], but not to my_array[1][3][3]. my_array[2][2][3] is further away still. This can affect performance as you increment one index or another - incrementing the last index is generally faster since you get more cache hits.

Example:

const int K = 400;
int my_array[K][K][K];

int main() {
    for (int i = 0; i < K; ++i) {
        for (int j = 0; j < K; ++j) {
            for (int k = 0; k < K; ++k) {
                #ifdef FAST
                    my_array[i][j][k] = 12;
                #else
                    my_array[k][j][i] = 12;
                #endif
            }
        }
    }
}

Output:

$ g++ looporder.cpp -o looporder && time ./looporder

real    0m2.500s
user    0m2.249s
sys     0m0.155s

$ g++ looporder.cpp -o looporder -DFAST && time ./looporder

real    0m0.516s
user    0m0.327s
sys     0m0.124s

$ g++ looporder.cpp -o looporder -O3 && time ./looporder

real    0m2.234s
user    0m2.140s
sys     0m0.093s

$ g++ looporder.cpp -o looporder -DFAST -O3 && time ./looporder

real    0m0.250s
user    0m0.171s
sys     0m0.108s

What the indices mean in terms of what's actually stored there is up to you - as you say it's just a question of "which way up" your cube is. So generally you choose them so that whatever you're incrementing in your innermost loop, is the last dimension.

like image 29
Steve Jessop Avatar answered Jan 26 '23 00:01

Steve Jessop