почему результаты чтения аппаратных счетчиков с papi зависят от позиции PAPI_library_init? - PullRequest
1 голос
/ 07 марта 2019

Я использую библиотеку PAPI для чтения аппаратных счетчиков. Я заметил, что порядок вызова инициализации PAPI_library_init (PAPI_VER_CURRENT) влияет на результаты, которые я получаю. Моя инициализация и чтение массива выглядит так:

int retval;

/*
     retval = PAPI_library_init(PAPI_VER_CURRENT);

     if (retval != PAPI_VER_CURRENT) {
       fprintf(stderr, "PAPI library init error!\n");
       exit(1);
     }
*/

      for(int i=0; i < arr_size; i++){
        array[i].value = 1;
        //_mm_clflush(&array[i]); flushing does not make difference. 
      }
      _mm_mfence();


      for(int i=0; i < arr_size; i++){
        temp = array[i].value ;
      }
      _mm_mfence();



      retval = PAPI_library_init(PAPI_VER_CURRENT);

      if (retval != PAPI_VER_CURRENT) {
        fprintf(stderr, "PAPI library init error!\n");
        exit(1);
      }

Необходимость второго цикла для чтения массива для протокола согласованности, я считаю, но здесь это не должно иметь большого значения. После этого я добавляю собственные события MEM_LOAD_RETIRED в набор событий, который я хочу прочитать, и использую PAPI_read вокруг этого третьего цикла (я читаю его до и после цикла и в конце выводю разницу):

for(int i=0; i < arr_size; i++){
       temp = array[i].value ;
     } 

где arr_size равен 1000, а каждый элемент массива имеет размер 64 байта (равен строке кэша). Я отключил всех предварительных сборщиков. Я компилирую с флагом gcc -O3 для оптимизации и библиотекой -lpapi. с этим кодом для третьего цикла я получаю:

L1_HIT: 64, L1_MISS: 1011, L2_HIT: 15, L2_MISS: 996.

Однако, если я раскомментирую PAPI_library_init до инициализации массива и прокомментирую его после этого, я получу следующие результаты:

L1_HIT: 73, L1_MISS: 1004, L2_HIT: 990, L2_MISS: 14.

Я тестирую это на сервере Skylake, размеры кэша:

L1d cache:             32K
L1i cache:             32K
L2 cache:              1024K
L3 cache:              22528K

Теперь я немного сбит с толку, почему инициализация папы влияет на эти результаты. это L2 ударил и пропустил это изменение. Все, что мне нужно, это третий цикл, и, как я полагаю, влияние первых двух циклов на счетчики не учитывается.

Таким образом, любая подсказка для этого была бы полезна, поскольку вся документация гласит: «PAPI_library_init () инициализирует библиотеку PAPI. Она должна быть вызвана перед использованием любых функций PAPI низкого уровня. Если ваше приложение использует потоки PAPI_thread_init (3) также следует вызывать перед выполнением любых вызовов в библиотеку, кроме PAPI_library_init (). "

...