Есть ли способ проверить, был ли недавно очищен кэш процессора?

На i386 linux. Предпочтительно в c/(c/posix std libs)/proc, если это возможно. Если нет, то есть ли какая-нибудь сборка или сторонняя библиотека, которая может это сделать?

Редактировать: я пытаюсь разработать тест, очищает ли модуль ядра строку кэша или весь процессор (с помощью wbinvd()). Программа запускается как root, но я бы предпочел остаться в пространстве пользователя, если это возможно.

3 ответа

Решение

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

Эта программа работает на моей коробке x86_64, чтобы продемонстрировать clflush, Сколько раз требуется, чтобы прочитать глобальную переменную, используя rdtsc, Будучи единственной инструкцией, привязанной непосредственно к тактовой частоте процессора, она напрямую использует rdtsc идеально подходит для этого.

Вот вывод:

взял 81 галочку
взял 81 галочку
флеш: взял 387 тиков
взял 72 тика

Вы видите 3 испытания: первое обеспечивает i находится в кеше (что и есть, потому что он был только обнулен как часть BSS), второе чтение i это должно быть в кеше. затем clflush пинки i выходит из кэша (вместе со своими соседями) и показывает, что перечитывание занимает значительно больше времени. Окончательное чтение подтверждает, что оно снова в кеше. Результаты очень воспроизводимы, и разница достаточно существенна, чтобы легко увидеть ошибки в кеше. Если вы хотели откалибровать накладные расходы rdtsc() Вы могли бы сделать разницу еще более заметной.

Если вы не можете прочитать адрес памяти, который вы хотите проверить (хотя даже mmap из /dev/mem должен работать для этих целей) вы можете сделать вывод, что вы хотите, если вы знаете размер строки кэширования и ассоциативность кэша. Затем вы можете использовать доступные ячейки памяти для проверки активности в наборе, который вас интересует.

Исходный код:

#include <stdio.h>
#include <stdint.h>

inline void
clflush(volatile void *p)
{
    asm volatile ("clflush (%0)" :: "r"(p));
}

inline uint64_t
rdtsc()
{
    unsigned long a, d;
    asm volatile ("rdtsc" : "=a" (a), "=d" (d));
    return a | ((uint64_t)d << 32);
}

volatile int i;

inline void
test()
{
    uint64_t start, end;
    volatile int j;

    start = rdtsc();
    j = i;
    end = rdtsc();
    printf("took %lu ticks\n", end - start);
}

int
main(int ac, char **av)
{
    test();
    test();
    printf("flush: ");
    clflush(&i);
    test();
    test();
    return 0;
}

Я не знаю ни одной универсальной команды для получения состояния кэша, но есть способы:

  1. Полагаю, это самое простое: если вы получили модуль ядра, просто разберите его и поищите команды аннулирования / очистки кэша (мне пришло только 3: WBINDVD, CLFLUSH, INVD).
  2. Вы только что сказали, что это для i386, но я думаю, вы не имеете в виду 80386. Проблема в том, что есть много разных с разными расширениями и функциями. Например, в новейшей серии Intel есть несколько регистров производительности / профилирования для системы кеша, которые вы можете использовать для оценки пропусков / попаданий в кеш / количества передач и тому подобного.
  3. Аналогично 2, очень зависит от системы, которую вы получили. Но когда у вас есть многопроцессорная конфигурация, вы можете наблюдать первый протокол согласования кэша (MESI) со вторым.

Вы упомянули WBINVD - afaik, который всегда завершит очистку, т.е. все строки кэша

Возможно, это не ответ на ваш конкретный вопрос, но вы пытались использовать профилировщик кеша, такой как Cachegrind? Он может использоваться только для профилирования кода пользовательского пространства, но, тем не менее, вы можете использовать его, например, перемещая код своей функции в пользовательское пространство, если он не зависит от каких-либо специфичных для ядра интерфейсов.

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

Другие вопросы по тегам