Это связано с местностью ссылки . Если вы обращаетесь к элементам в том же порядке, в каком они хранятся в памяти, это будет намного быстрее, чем доступ к ним по очереди, поскольку кэши памяти и пропускная способность памяти будут использоваться гораздо более эффективно.
Вышесказанное объясняет, что вторая версия быстрее первой, и это именно то, что происходит на моей коробке:
aix@aix:~$ time ./ver1
real 0m29.421s
aix@aix:~$ time ./ver2
real 0m2.198s
Вот код, который я использую для выделения массива:
double a = 0.5;
int width = 2048;
int height = 2048;
double* data = new double[height * width];
double** image = new double*[height];
for (int i = 0; i < height; i++) {
image[i] = data + i * width;
}
Версия 1 раз следующий цикл:
for (int iter = 0; iter < 100; iter++) {
for(int w=0; w<width; w++) {
for(int h=1; h<height; h++) {
image[h][w] = (1-a)*image[h][w] + a*image[h-1][w];
}
}
}
Цикл версии 2:
for (int iter = 0; iter < 100; iter++) {
for(int h=0; h<height; h++) {
for(int w=1; w<width; w++) {
image[h][w] = (1-a)*image[h][w] + a*image[h][w-1];
}
}
}
Скомпилировано с g++
4.4.3 с -O3
и запущено на коробке Xeon некоторого описания (64-битная Ubuntu).
Если вы все еще на 100% уверены, что видите эффект , противоположный , должно быть что-то принципиально иное в том, что вы делаете, по сравнению с тем, что я делаю. Это может помочь, если вы сообщите нам размеры вашего изображения и как именно оно будет выделено (для того, чтобы помочь установить структуру памяти).