If you define:
int my_array[10][10][10];
One thing that is required is the value of the storage indexes. my_array[1][2][3] is adjacent in memory until my_array[1][2][4] , but not until my_array[1][3][3] . my_array[2][2][3] even further. This can affect performance as you increase one index or the other - incrementing the last index tends to be faster as 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 } } } }
Conclusion:
$ 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 indexes mean in terms of what is actually stored there is up to you - as you say, this is just a question of how your cube is βin what wayβ. Therefore, usually you choose them so that everything that you increase in your inner cycle is the last dimension.
source share