Что означает «сбои страниц» в «perf stat» по отношению к «незадействованным бэкэнд-циклам»? - PullRequest
0 голосов
/ 14 мая 2018

Я написал простую программу умножения матриц, чтобы продемонстрировать эффект кэширования и измерения производительности с помощью perf. Две функции для сравнения относительной эффективности: sqmat_mult и sqmat_mult_efficient:

void sqmat_mult(int x, const int a[x][x], const int b[x][x], int m[x][x])
{
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < x; j++) {
            int sum = 0;
            for (int k = 0; k < x; k++) {
                sum += a[i][k] * b[k][j]; // access of b array is non sequential
            }
            m[i][j] = sum;
        }
    }
}


static void sqmat_transpose(int x, int a[x][x])
{
    for (int i = 0; i < x; i++) {
        for (int j = i+1; j < x; j++) {
            int temp = a[i][j];
            a[i][j] = a[j][i];
            a[j][i] = temp;
        }
    }     
}

void sqmat_mult_efficient(int x, const int a[x][x], int b[x][x], int m[x][x])
{
    sqmat_transpose(x, b);

    for (int i = 0; i < x; i++) {
        for (int j = 0; j < x; j++) {
            int sum = 0;
            for (int k = 0; k < x; k++) {
                sum += a[i][k] * b[j][k];  // access of b array is sequential
            }
            m[i][j] = sum;
        }
    }

    sqmat_transpose(x, b);
}

Однако, когда я запускаю perf stat на основе этих двух функций, я запутался в статистике "сбоев страниц". Выход для sqmat_mult:

     428374.070363      task-clock (msec)         #    1.000 CPUs utilized          
               128      context-switches          #    0.000 K/sec                  
               127      cpu-migrations            #    0.000 K/sec                  
            12,334      page-faults               #    0.029 K/sec                  
 8,63,12,33,75,858      cycles                    #    2.015 GHz                      (83.33%)
    2,89,73,31,370      stalled-cycles-frontend   #    0.34% frontend cycles idle     (83.33%)
 7,90,36,10,13,864      stalled-cycles-backend    #   91.57% backend cycles idle      (33.34%)
 2,24,41,64,76,049      instructions              #    0.26  insn per cycle         
                                                  #    3.52  stalled cycles per insn  (50.01%)
    8,84,30,79,219      branches                  #   20.643 M/sec                    (66.67%)
       1,04,85,342      branch-misses             #    0.12% of all branches          (83.34%)

     428.396804101 seconds time elapsed

В то время как выход для sqmat_mult_efficient:

       8534.611199      task-clock (msec)         #    1.000 CPUs utilized          
      39876.726670      task-clock (msec)         #    1.000 CPUs utilized          
                11      context-switches          #    0.000 K/sec                  
                11      cpu-migrations            #    0.000 K/sec                  
            12,334      page-faults               #    0.309 K/sec                  
 1,19,87,36,75,397      cycles                    #    3.006 GHz                      (83.33%)
      49,19,07,231      stalled-cycles-frontend   #    0.41% frontend cycles idle     (83.33%)
   50,40,53,90,525      stalled-cycles-backend    #   42.05% backend cycles idle      (33.35%)
 2,24,10,77,52,356      instructions              #    1.87  insn per cycle         
                                                  #    0.22  stalled cycles per insn  (50.01%)
    8,75,27,87,494      branches                  #  219.496 M/sec                    (66.68%)
         50,48,390      branch-misses             #    0.06% of all branches          (83.33%)

      39.879816492 seconds time elapsed

При транспонированном умножении количество "незадействованных бэкэнд-циклов" значительно уменьшается, как и ожидалось. Это связано с малым временем ожидания получения когерентной памяти. Что меня смущает, так это то, что количество «сбоев страниц» одинаково. Сначала я подумал, что это может быть проблемой переключения контекста, поэтому я запустил программу с расписанием SCHED_FIFO и приоритетом 1. Количество переключений контекста уменьшилось примерно с 800 до 11, но «сбои страниц» остались такими же, как и раньше.

Размер матрицы, которую я использую, равен 2048 x 2048, поэтому весь массив не поместится на странице 4K. Он также не помещается во весь мой кэш (4MiB в моем случае), поскольку размер трех матриц (3 *2048* 2048 * sizeof (int) == 48MiB) значительно превышает общий кэш avaibale. Предполагая, что «ошибки страницы» здесь относятся к пропаданию TLB или кешу, я не вижу, как эти два алгоритма могут иметь одинаковое число. Я понимаю, что значительное улучшение эффективности, которое я вижу, связано с тем, что происходит попадание в кэш L1, но это не означает, что передача из ОЗУ в кэш не играет никакой роли.

Я также провел еще один эксперимент, чтобы проверить, масштабируются ли «ошибки страницы» в соответствии с размером массива. Как и ожидалось.

Так что мои вопросы -

  1. Правильно ли я полагаю, что "сбои страниц" означают промах TLB или промах кэша?
  2. Почему «ошибки страниц» одинаковы для обоих алгоритмов?

1 Ответ

0 голосов
/ 14 мая 2018

Правильно ли я полагаю, что "сбои страниц" означают промах TLB или промах кэша?

Нет.Ошибка страницы возникает, когда виртуальная память не сопоставлена ​​с физической памятью.Для этого есть две типичные 1 причины:

  1. Данные были перемещены из физической памяти на диск (подкачка).Когда происходит сбой страницы, данные перемещаются обратно в физическую память, и сопоставление из виртуальной памяти восстанавливается.
  2. Область памяти была отложена.Только при первом выделении фактическая физическая память будет выделена соответствующей виртуальной памяти.

Теперь сбой страницы, вероятно, 2 произойдет только после пропадания кэша и пропуска TLB,потому что TLB хранит только фактические отображения, а кэш будет содержать только данные, которые также находятся в основной памяти.

Вот упрощенная диаграмма того, что происходит:

decision making process for memory lookup Изображение Аравинда Кришны CC BY-SA 4.0 , из Wikimedia Commons

Почему "сбои страниц" одинаковы для обоих алгоритмов?

Все ваши данные помещаются в физическую память, поэтому в вашем случае обмен не происходит.Это оставляет вас с 2), что происходит один раз для каждой виртуальной страницы.Вы используете 48 МБ памяти, которая использует 12288 страниц размером 4 КБ.Это то же самое для обоих алгоритмов и почти точно, что вы измеряете.

1 Дополнительные причины могут быть связаны с балансировкой ввода / вывода с отображением в памяти.

2 Полагаю, вы могли бы построить архитектуру, в которой TLB содержит информацию о несопоставленных виртуальных адресах или память не содержит кеш, но я сомневаюсь, что такая архитектура существует.

...