Вероятно, до поведения кэша процессора (на 12 МБ ваши изображения намного превышают кеш-память L2 256 КБ в ARM Cortex A8, находящемся в iphone3gs).
Первый пример обращается к массиву чтения в последовательном порядке, который является быстрым, но должен иметь доступ к массиву записи не по порядку, что является медленным.
Второй пример - обратный - записывающий массив написан быстрым последовательным порядком, а массив чтения обращается медленнее. Ошибки записи, очевидно, менее дорогостоящие в рамках этой рабочей нагрузки, чем прочтения промахов.
Рекомендуется прочитать статью Ульриха Дреппера What Every Programmer Should Know About Memory, если вы хотите узнать больше об этом.
Обратите внимание, что если у вас есть эта операция завернутой в функцию, то вам поможет оптимизатору генерировать лучший код, если вы используете restrict
спецификатора на ваших аргументах указателей, например:
void reorder(uint32_t restrict *buffer1, uint32_t restrict *buffer2)
{
int i = 0;
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
buffer1[x+y*width] = buffer2[i++];
}
(The restrict
дает обещание компилятору, что данные, на которые указывают два указателя, не перекрываются, что в этом случае необходимо, чтобы функция имела смысл в любом случае).
Прыжки между различными страницами памяти? Доступ к памяти - это не постоянная работа, в отличие от того, что вы предполагаете в классе алгоритмов, хотя вы, вероятно, можете установить верхнюю границу для данной архитектуры. –
Пара вопросов: во-первых, вы тестируете на сборке отладки или выпуска. Во-вторых, как вы определяете время? – Toji
Что такое сборка для сегмента кода? Это звучит как глупость архитектуры, если я не пропущу что-то очевидное. –