Я использую PAPI для подсчета результатов доступа к кэш-памяти L1.В основном нативные события дают ожидаемые результаты, однако есть один случай, когда L1_MISS не является точным.У меня есть объект размером 64 и изменчивый массив из 100 000 элементов, как показано в коде:
typedef struct _object{
int value;
char pad[60];
} object;
#define arr_size 100000
volatile object array [arr_size];
void * loop (int arg){
/* Threads are set in NUMA2 */
int temp;
for(int i=0; i < arr_size; i++){
temp = array[i].value;
}
}
Я тестирую процессор Skylake с двумя узлами NUMA.Я отключил предварительных сборщиков.Компиляция с gcc -O3.Сценарий следующий: из основного процесса, заданного в NUMA1, я инициализирую массив и очищаю строки кэша.Затем я создаю 5 потоков, которые читают тот же массив из NUMA2, вызывая функцию loop .После того, как все они завершены, я зацикливаюсь на массиве из основного процесса, читая каждый элемент и отслеживаю результаты доступа к кэш-памяти L1:
int main(int argc, char* argv[]){
/* Main thread is set in NUMA1 */
/* Array is initialized and flushed from the cache*/
/* 5 threads are created with pthread_create, that call loop function,
and waited to finish by calling pthread_join*/
int tmp;
/*Hardware counters are counted for this loop*/
for(int i=0; i < arr_size; i++){
tmp = array[i].value;
}
}
Я читаю эти 5 собственных счетчиков событий:
MEM_INST_RETIRED.ALL_LOADS: 100095
L1D.REPLACEMENT: 100246
MEM_LOAD_RETIRED.L1_HIT: 113
MEM_LOAD_RETIRED.L1_MISS: 56
MEM_LOAD_RETIRED.FB_HIT: 55
Ожидалось, что L1_MISS увидит около 100 000, потому что элементы не выбираются в кеш, и это чтение в main должно вызвать промах.также ALL_LOADS не равно сумме трех счетчиков: L1_HIT + L1_MISS + FB_HIT.Несмотря на то, что L1D.REPLACEMENT, кажется, имеет смысл в этом случае, подсчитывая замены строк данных L1D, я не убежден в этом, поскольку он также учитывает предварительную выборку при включении.
Я не понимаю, что может бытьпричина того, что счетчик MEM_LOAD_RETIRED.L1_MISS не видит события, вызванные операцией чтения в main, только в этом конкретном сценарии.Как, например, если потоки из NUMA2 вместо чтения изменяют элемент массива, то для того же цикла я получаю L1_MISS: 99818. поэтому любое предложение будет полезным.Я попытался представить основной каркас кода.Если какие-либо части комментируемых пунктов важны, я также могу добавить их.