2010-11-01 4 views
3

Это часть вывода cachegrind. Эта часть кода выполнена в 1224 раза. elmg1 - это массив без знака длиной 16 x 20. Размер кеша L1 для моей машины составляет 32 КБ, размер строки кеша 64 Б и 8-полосная ассоциативная ассоциация.Интерпретация вывода Cachegrind

  1. для (I = 0; я < 20; я ++) 78336 2448 2 50184 0 0 0 0 тысячу двести двадцать-четыре
  2. {
  3. telm01 = elmg1 [I]; 146 880 0 0 73 440 0 0 24 480 0 0
  4. telm31 = (telm01 < < 3)^val1; 97 920 0 0 48 960 0 0 24 480 0 0
  5. telm21 = (telm01 < < 2)^(val1 >> 1); 146,880 1,224 1 48,960 0 0 24,480 0 0
  6. telm11 = (telm01 < < 1)^(val1 >> 2); 0 0 146880 0 48960 0 24480 0 0
  7. }

A. Причина я положил его здесь, является то, что в 3-й линии внутри для цикла, я вижу ряд I1 скучает (один L2 пропустите также). Это несколько сбивает с толку, и я не мог догадаться, почему?

B. Я пытаюсь оптимизировать (время) часть кода. Выше всего это небольшой фрагмент. Я думаю, что в моей памяти программы мне очень дорого стоило. Как и в приведенном выше примере, elmg1 представляет собой массив размером 16 x 20 беззнаковых длин. Когда я пытаюсь использовать его в коде, всегда есть некоторые промахи, и в моей программе эти переменные происходят много. Какие-либо предложения?

C. Мне нужно выделить и (иногда инициализировать) эти беззнаковые длинные. Можете ли вы предложить, какой из них я должен предпочесть, объявление calloc или массив, а затем явную инициализацию. Кстати, будет ли какая-то разница в том, как кэш обращается к ним?

Спасибо.

ответ

3

Вы пытались развернуть цикл?

  1. Я бы не стал беспокоиться о промахах L1 прямо сейчас. Также один L2 пропустил 1224 раза в порядке, процессор должен загрузить значения в кеш в какой-то момент.
  2. Какой процент пропусков L2 составляет этот код по сравнению с остальной частью программы?
  3. Используйте calloc(), если размер массива всегда один и тот же, и вы используете константы для размера, тогда компилятор может оптимизировать нулевое значение массива. Также единственное, что могло бы повлиять на использование строк в кешках, - это выравнивание, а не то, как оно было инициализировано.

Редактировать: Число, где трудно читать этот путь и читать их неправильно в первый раз.

позволяет убедиться, что я читаю номера прямо на линии 5:

Ir 146,880 
I1mr 1,224 
ILmr 1 
Dr 48,960 
D1mr 0 
DLmr 0 
Dw 24,480 
D1mw 0 
DLmw 0 

L1 кэш разделяется на два 32KByte кэширует один для кода I1 и один из данных D1. IL & DL - это кеш L2 или L3, который совместно используется как данными, так и инструкциями.

Большое количество I1mr - это команда пропускает не пропуски данных, это означает, что код цикла выталкивается из кеша инструкций I1.

I1 промахивается по строке 1 & 5 всего 3672, что составляет 3 раза 1224, поэтому каждый раз, когда цикл запускается, вы получаете 3 промаха кэша I1 с линиями кеша 64 бит, что означает, что размер кода цикла составляет 128-192 байта для покрытия 3 строки кэша. Таким образом, те I1 промахиваются в строке 5, потому что именно здесь код цикла пересекает последнюю строку кэша.

I would recommend using KCachegrind for viewing the results from cachegrind

Edit: Подробнее о строках кэша.

Этот код цикла не похож на то, что он сам вызывает 1224 раза, поэтому это означает, что есть больше кода, который выталкивает этот код из кеша I1.

Ваш кеш I1 объемом 32 Кбайт разделен на 512 строк кэша (по 64 байта). Компонент «8-позиционная ассоциативная» означает, что каждый адрес памяти отображается только 8 из этих 512 строк кэша. Если вся ваша программа - это один непрерывный блок размером 32 Кбайт памяти, то все они будут вписываться в кеш I1, и ни один из них не будет удален. Вряд ли это не так, и будет храниться более 8 64-битных блоков кодирования кода для тех же 8 строк кеша. Допустим, что вся ваша программа имеет 1 Мбайт кода (включая библиотеки), тогда каждая группа из 8 строк кэша будет иметь около 32 (1 Мбайт/32 Кбайт) фрагментов кода для тех же 8 строк кеша.

Read this lwn.net article for all the gory details about CPU caches

компилятор не всегда может определить, какие функции программы будут горячие точки (так называемый много много раз) и который будет codespots (т.е. код обработчика ошибок, которые почти никогда не работает). GCC имеет атрибуты функций hot/cold, которые позволят вам отмечать функции как горячие/холодные, это позволит компилятору группировать горячие функции вместе в одном блоке памяти, чтобы улучшить использование кеша (например, холодный код не будет вызывать горячий код из кэша).

В любом случае эти промахи I1 действительно не стоят времени беспокоиться.

+0

A. Это нормально, но почему в строке 5 отсутствуют пропуски кеша, тогда как в строке 3 меньше. 4. Нужно ли самому определять предмет выравнивания, я читал, что malloc по умолчанию обеспечивает выравнивание по 8/16 байт , – anup

+0

Да, malloc должен обеспечивать выравнивание по 8 байт, но это не то же самое, что выравнивание кеша 64Byte. Выравнивание кеша важно только тогда, когда у вас есть массив объектов по 64 байта каждый. Если в массиве не выделен кеш, то доступ к любому одному элементу массива может привести к двум промахам в кэше вместо одного. Но выравнивание кеша не является проблемой в этом случае. – Neopallium

+0

Спасибо за ваш ответ. Но, одна вещь, что я не понял, что это касается 3 строк кэша? Должно быть больше строк кеша. – anup

Смежные вопросы