Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Термины / Cache Miss (Промах кэша)

Cache Miss (Промах кэша)

Cache Miss(промах кэша) случается, когда запрашиваемые данные отсутствуют в кэше и их нужно подгружать из основного источника.

Так, например, у любого современного процессора есть кэш, в котором он хранит недавно прочитанные блоки оперативной памяти и обращение к кэшированным данным происходит существенно быстрее, чем "перекачивание" этих же данных из оперативной памяти на кристалл процессора. Если всё-таки запрашиваются данные, которые в данный момент в кэше отстутствуют или они уже не актуальны, они вместе с другими находящимися к ним близко данными, поступают в кэш процессора.

При программировании высокопроизводительных приложений важно важно научиться писать т.н. "cache-friendly", дружественный с кешем код. Чтобы понять, что это такое, рассмотрим несложный пример:

const int count  = 1000000;
int *staticRefs[count];
int *dynamicRefs[count];

int staticArray[count];

int main()
{
  for(int i = 0; i < count; i++)
  {
    staticArray[i] = 0;
    staticRefs[i] = &staticArray[i];

    int *val = new int(0);
    dynamicRefs[i] = val;
  }
  //первый цикл
  for(int i = 0; i < count; i++)
  {
    (*staticRefs[i])++;
  }
  //второй цикл
  for(int i = 0; i < count; i++)
  {
    (*dynamicRefs[i])++;
  }
}
(полный код примера можно посмотреть здесь)
Здесь в двух циклах делается, казалось бы, одно и то же - увеличиваются значения всех чисел, на которые ссылаются оба массива. Казалось бы, чисел одинаковое количество и работа проделывается одинаковая, но первый цикл стабильно работает в четыре раза быстрее. Происходит это потому что данные, на которые ссылается первый массив, лежат в памяти плотно, и, прочитав i-й элемент этого массива, в кэш ещё автоматически попадают сколько-то следующих за ним элементов, обращение к которым будет уже производиться очень быстро. Во втором же массиве хранятся ссылки на элементы, выделенные оператором new, который, хоть и пытается располагать данные поплотнее, удаётся это ему, как видим, с переменным успехом, данные оказываются разбросанными по памяти хаотично, и при чтении i-го элемента следующие после него в кэш попадают редко.

Часто для того, чтобы увеличить "плотность" данных(ещё она называется локальностью) в узких местах программы, используются свои менеджеры памяти. Секрет в том, что если мы заранее знаем, что нам понадобится выделять, к примеру, только куски памяти одинакового размера или нам не придётся их удалять, менеджер памяти может работать существенно эффективнее "многоцелевого" стандартного.

Особенно часто нелокальность данных убивает производительность, если в приложении широко используется динамическое выделение памяти стандартными средствами вроде new или malloc для большого количества маленьких объектов - они опять же оказываются разбросаны по памяти "как попало" и простой доступ к ним существенно замедляется.

Что такое Cache Miss (Промах кэша)?

10 июня 2009

#cache, #CPU architecture, #performance

2001—2018 © GameDev.ru — Разработка игр