Изменить: я обновил свой вопрос с подробностями моего теста
Для целей бенчмаркинга я пытаюсь настроить 1 ГБ страниц в системе Linux 3.13, работающей на двух процессорах Intel Xeon 56xx ( "Westmere" ). Для этого я изменил параметры загрузки, чтобы добавить поддержку 1 ГБ страниц (10 страниц). Эти параметры загрузки содержат только 1 ГБ страниц, а не 2 МБ. Выполнение hugeadm --pool-list
приводит к:
Size Minimum Current Maximum Default
1073741824 10 10 10 *
Учитываются мои параметры загрузки ядра. В моем тесте я выделяю 1GiB памяти, что хочу получить поддержку на огромной странице 1GiB, используя:
#define PROTECTION (PROT_READ | PROT_WRITE)
#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)
uint64_t size = 1UL*1024*1024*1024;
memory = mmap(0, size, PROTECTION, FLAGS, 0, 0);
if (memory == MAP_FAILED) {
perror("mmap");
exit(1);
}
sleep(200)
Глядя на /proc/meminfo
, пока скамья спит (вызов sleep
выше), мы видим, что была выделена одна огромная страница:
AnonHugePages: 4096 kB
HugePages_Total: 10
HugePages_Free: 9
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
Примечание.. Я отключил THP (через файловую систему /sys
) перед запуском скамейки, поэтому я думаю, что поле AnonHugePages
, сообщенное /proc/meminfo
, представляет собой огромные страницы, выделенные THP до останавливая его.
На этом этапе мы можем думать, что все в порядке, но, к сожалению, моя скамейка заставляет меня думать, что используется много страниц 2MiB, а не одна страница 1GiB. Вот объяснение:
Эта скамья случайным образом получает доступ к выделенной памяти с помощью преследования курсора: первый шаг заполняет память, чтобы включить преследование цепей (каждая ячейка указывает на другую ячейку), а на втором этапе скамья перемещается по памяти с помощью
pointer = *pointer;
Используя системный вызов perf_event_open
, я подсчитываю данные прочтений TLB только для второго шага скамьи. Когда размер выделенной памяти равен 64MiB, я подсчитываю очень небольшое число, 0,01% из моих 6400000 обращений к памяти, данных пропущенных пропусков TLB. Все обращения сохраняются в TLB. Другими словами, 64 Мбайт памяти может храниться в TLB. Как только размер выделенной памяти превышает 64 мегабайта, я вижу, что данные tlb читают промахи. Для размера памяти, равного 128 MiB, у меня есть 50% моих 6400000 обращений к памяти, которые пропустили в TLB. 64MiB представляется размером, который может вписываться в TLB и 64MiB = 32 записи (как указано ниже) * 2MiB-страницы. Я пришел к выводу, что я не использую страницы 1GiB, а 2MiB.
Вы можете увидеть какое-либо объяснение этого поведения?
Кроме того, инструмент cpuid
сообщает о tlb в моей системе следующее:
cache and TLB information (2):
0x5a: data TLB: 2M/4M pages, 4-way, 32 entries
0x03: data TLB: 4K pages, 4-way, 64 entries
0x55: instruction TLB: 2M/4M pages, fully, 7 entries
0xb0: instruction TLB: 4K, 4-way, 128 entries
0xca: L2 TLB: 4K, 4-way, 512 entries
L1 TLB/cache information: 2M/4M pages & L1 TLB (0x80000005/eax):
L1 TLB/cache information: 4K pages & L1 TLB (0x80000005/ebx):
L2 TLB/cache information: 2M/4M pages & L2 TLB (0x80000006/eax):
L2 TLB/cache information: 4K pages & L2 TLB (0x80000006/ebx):
Как вы можете видеть, информация о страницах 1GiB отсутствует. Сколько таких страниц может быть кэшировано в TLB?