В чем проблема с использованием потокового доступа для измерения максимальной пропускной способности памяти? - PullRequest
1 голос
/ 18 апреля 2019

Используя Skylake в качестве примера, его строка кэша составляет 64B.

Я попытался написать простую программу, чтобы увидеть, какую максимальную пропускную способность памяти я могу использовать. В приведенном ниже коде я намеренно сделал шаг 64B, чтобы каждая загрузка получала разные строки кэша (64B). Я собираю время, используемое для завершения 10M загрузок, а затем вычисляю загруженную память, умножая количество загрузок на 64B.

Затем я запускаю потоки, которые синхронизируют объявления, и запускаю код ниже параллельно. Таким образом, когда все потоки заканчиваются, общий объем загруженной памяти составляет total * NUM_OF_THREADS * 64B . Затем я делю это с (end_time-start_time).

Полученная мной пропускная способность намного выше теоретической максимальной пропускной способности памяти для Skylake. Так что это не правильно. Но я не знаю, что не так с моим расчетом.

Единственное, что я могу сделать, - это то, что, возможно, BW памяти не заполнен, процессор предварительно выбирает следующие строки кэша, так что многие из нагрузок фактически загружаются из кэша. Но так как моя встроенная сборка представляет собой плотную последовательность загрузок памяти, я не уверен, как подтвердить мои предположения.

Есть комментарии? Спасибо.

   st = start_timing()
        do {
          for (i=0; i< 10; i++) {
            asm volatile("movl 0x0(%[P]),%[sum]\n\t"
                         "movl 0x40(%[P]),%[sum]\n\t"
                         "movl 0x80(%[P]),%[sum]\n\t"
                         "movl 0xc0(%[P]),%[sum]\n\t"
                         "movl 0x100(%[P]),%[sum]\n\t"
                         "movl 0x140(%[P]),%[sum]\n\t"
                         "movl 0x180(%[P]),%[sum]\n\t"
                         "movl 0x1c0(%[P]),%[sum]\n\t"
                         "movl 0x200(%[P]),%[sum]\n\t"
                         "movl 0x240(%[P]),%[sum]\n\t"
                         "movl 0x280(%[P]),%[sum]\n\t"
                         "movl 0x2c0(%[P]),%[sum]\n\t"
                         "movl 0x300(%[P]),%[sum]\n\t"
                         "movl 0x340(%[P]),%[sum]\n\t"
                         "movl 0x380(%[P]),%[sum]\n\t"
                         "movl 0x3c0(%[P]),%[sum]\n\t"
                         "movl 0x400(%[P]),%[sum]\n\t"
                         "movl 0x440(%[P]),%[sum]\n\t"
                         "movl 0x480(%[P]),%[sum]\n\t"
                         "movl 0x4c0(%[P]),%[sum]\n\t"
                             : [P]"+r"(p), [sum]"+r"(sum)
                             : );
          }   
          total += 200;
          p = q+ ((total%1000000)<<6);

        } while (total < 10000000);
    et = end_timing()

    bw = (total * 64)/(et-st)

1 Ответ

1 голос
/ 18 апреля 2019

Да, загрузка двойного слова из каждой строки кэша является хорошим способом для измерения пропускной способности кэша / пропускной способности памяти для кэшей, отличных от L1d.(Если данные остаются горячими в L1d, вам нужно измерить узкое место при передаче их через загрузочные блоки выполнения в регистры; если у вас нет AVX512, требуется несколько инструкций для чтения всей строки кэша.)

Возможно, выполучать попадания в кэш L1d или L2.Если вы никогда не записывали память, она будет отображаться при копировании при записи на одну и ту же физическую нулевую страницу, если она находится в BSS или выделена с помощью malloc.

Или просто, что разные ядра имеют свои собственные частные кэши L1d,См. Как кеш может быть таким быстрым? на электронике.Однако, если вы на самом деле касаетесь 10 МБ физической памяти, это больше, чем у четырехъядерного рабочего стола SKL.Если у вас Skylake Xeon с большим объемом кэша L3, то да, совокупная пропускная способность, конечно, может быть значительно выше, чем ОЗУ.

Кроме того, http://blog.stuffedcow.net/2013/01/ivb-cache-replacement/ показывает, что замена L3 не является строго псевдо-LRU;в последнее время он адаптивен, поэтому он может быть более устойчивым, чем вы ожидаете, исключив зацикливание на ОЗУ.10 МБ может быть достаточно маленьким, чтобы получить несколько попаданий L3 с общим объемом L3 8 МБ на четырехъядерном процессоре i7.


asm volatile остановит его оптимизацию, а вход "+r"(pointer) должен бытьхорошо, чтобы увидеть ваши обновления указателя.Компилятор не «знает», что asm читает указанную память (потому что вы этого не сказали, и нет "memory" clobber), поэтому любые более ранние хранилища в буфере могут быть оптимизированы как мертвые хранилища..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...