Опубликовано
- 1 мин чтения
Как данные влияют на производительность

Хочу рассказать о том, насколько важно способ инициализации данных для достижения максимальной производительности кода.
Рассмотрим следующий синтетический пример.
- Массивы
t1
иt2
содержат информацию о транзакциях. - Два метода,
Setup1
иSetup2
, инициализируют массивыt1
иt2
соответственно:Setup1
– двумя цикламиfor
, аSetup2
– одним. - Метод
Sum
позволяет вычислить сумму транзакций в массивахt1
илиt2
.

Вопрос: при каком способе инициализации расчёт суммы в массивах Sum(t1) + Sum(t2)
выполнится быстрее?
Правильный ответ: Sum(t1) + Sum(t2)
рассчитывается быстрее, если массивы инициализировать двумя циклами for
.

Почему так? Всё дело в кэше данных процессора. Я уже писал пост на эту тему, но тогда рассматривал два разных алгоритма для обхода одной и той же матрицы. В данном случае алгоритм не меняется, но данные инициализируются по-разному.
Если массивы t1
и t2
инициализировать одним циклом for, то в памяти это выглядит примерно так:
t1[0], t2[0], t1[1], t2[1], t1[2], t2[3], ...
При расчёте, например, Sum(t1)
, в самом начале происходит обращение к элементу t1[0]. Копирование данных из памяти в кэш происходит блоками по 64 байта — это размер линии кэша большинства современных процессоров. Из-за этого в кэш попадают элементы массива t2
, хотя методу Sum нужны элементы только одного массива. В результате увеличивается количество промахов кэша.
Если массивы t1
и t2
инициализировать двумя циклами for
, то локальность данных более высокая, что снижает количество промахов кэша:
t1[0], t1[1], t1[2], t1[3], ... t2[0], t2[1], t2[2], t2[3], ...