Во-первых, инклюзивные иерархии кэша могут быть не такими распространенными, как вы предполагаете. Например, я не думаю, что какие-либо современные процессоры Intel - ни Nehalem, ни Sandybridge, ни, возможно, Atoms - имеют L1, который включен в L2. (Однако в Nehalem и, вероятно, в Sandybridge оба L1 и L2 включены в L3; используется текущая терминология Intel, FLC и MLC в LLC.)
Но это не обязательно имеет значение. В большинстве иерархий кеша, если у вас пропущена кеш-память L1, эта пропасть, вероятно, будет найдена в L2. Не имеет значения, если это включено или нет. Чтобы поступить иначе, вам понадобится что-то, что скажет вам, что данные, которые вас интересуют (вероятно) не в L2, вам не нужно искать. Хотя я разработал протоколы и типы памяти, которые делают это - например, тип памяти, который кэшируется только в L1, но не в L2, полезен для таких вещей, как графика, где вы получаете преимущества объединения в L1, но когда вы многократно сканируете большой массив, поэтому кэширование в L2 не очень хорошая идея , Немного не знаю, кто их сейчас отправляет.
В любом случае, вот несколько причин, по которым количество пропусков кэша L1 может не совпадать с числом обращений к кэшу L2.
Вы не говорите, над какими системами вы работаете - я знаю, что мой ответ применим к Intel x86, таким как Nehalem и Sandybridge, чей мониторинг производительности EMON позволяет подсчитывать такие вещи, как пропуски кэша L1 и L2 и т. Д. Это, вероятно, также применимо к любому современному микропроцессору с аппаратными счетчиками производительности на случай отсутствия кеша, например, в ARM и Power.
Большинство современных микропроцессоров не останавливаются при первом промахе кэша, но продолжают пытаться выполнить дополнительную работу. В целом это часто называют спекулятивным исполнением. Кроме того, процессор может быть в порядке или не в порядке, но, хотя последний может дать вам еще большие различия между количеством пропусков L1 и количеством доступов L2, это необязательно - вы можете получить это поведение даже при процессоры заказов.
Краткий ответ: многие из этих спекулятивных обращений к памяти будут находиться в одной и той же ячейке памяти. Они будут раздавлены и объединены.
Событие производительности "Кэш L1 пропущен", вероятно, [*] подсчитывает количество (спекулятивных) инструкций, которые пропустили кэш L1. Который затем выделяет аппаратную структуру данных, называемую в Intel буфером заполнения, в некоторых других местах регистр обработки пропущенных состояний. Последующие пропуски кеша в той же строке кеша пропустят кеш L1, но дойдут до буфера заполнения и будут уничтожены. Только один из них, обычно первый, будет отправлен на L2 и засчитан как доступ L2.)
Кстати, для этого может быть событие производительности: Squashed_Cache_Misses.
Также может быть событие производительности L1_Cache_Misses_Retired. Но это может быть недооценкой, так как спекуляция может вытянуть данные в кеш, и пропадание кеша при удалении может никогда не произойти.
([*] Кстати, когда я говорю «вероятно», я имею в виду «На машинах, которые я помогал проектировать». Почти наверняка. Возможно, мне придется проверить определение, посмотрите на RTL, но я бы хотел очень удивлен, если нет. Это почти гарантировано.)
например. представьте, что вы получаете доступ к байтам A [0], A [1], A [2], ... A [63], A [64], ...
Если адрес A [0] равен нулю по модулю 64, то A [0] .. A [63] будет находиться в той же строке кэша на машине с 64 байтовыми строками кэша. Если код, который использует их, прост, вполне возможно, что все они могут быть спекулятивно выданы. QED: 64 спекулятивных доступа к памяти, 64 кеша L1 отсутствует, но только один доступ к памяти L2.
(Кстати, не ожидайте, что числа будут такими чистыми. Возможно, вы не получите ровно 64 доступа L1 на доступ L2.)
Еще несколько возможностей:
Если количество обращений к L2 больше, чем количество пропущенных кэш-памяти L1 (я почти никогда не видел его, но это возможно), у вас может быть шаблон доступа к памяти, который сбивает с толку аппаратную предварительную выборку. Аппаратный prefetcher пытается предсказать, какие строки кэша вам понадобятся. Если предварительный выборщик плохо предсказывает, он может извлечь строки кэша, которые вам на самом деле не нужны. Часто наблюдается производительность, которая никогда не подсчитывает Prefetches_from_L2 или Prefetches_from_Memory.
Некоторые машины могут отменить спекулятивный доступ, который вызвал пропадание кэша L1, прежде чем они будут отправлены в L2. Тем не менее, я не знаю, что Intel делает это.