В качестве примера возьмем Skylake, его строка кэша составляет 64 байта.
Я попытался написать простую программу, чтобы узнать, какую максимальную пропускную способность памяти я могу потреблять. В приведенном ниже коде я намеренно сделал шаг 64 байта, чтобы при каждой загрузке извлекалась отдельная строка кэша (64 байта). Я собираю время, затраченное на завершение 10 М загрузок, а затем вычисляю загруженную память, умножая количество загрузок на 64 Б.
Затем я запускаю потоки, которые синхронизируют объявление, запуская код ниже параллельно. Таким образом, когда все потоки завершатся, общая загруженная память составит 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)
perf stat
для подсчета промахов кеша? - person Peter Cordes   schedule 18.04.2019MEM_LOAD_RETIRED.L1_HIT
,MEM_LOAD_RETIRED.L2_HIT
иMEM_LOAD_RETIRED.L3_HIT
. Я предполагаю, что вы получаете много обращений L1, но трудно сказать, почему, не видя весь код. Что вы имели в виду, говоря, что я использую производительность, чтобы измерить фактическое потребление пропускной способности памяти, которое составляет около 95 ГБ / с? Например как? - person Hadi Brais   schedule 19.04.2019