Подтвердить что ты не робот

Как использовать страницы Intel Westmere 1GB в Linux?

Изменить: я обновил свой вопрос с подробностями моего теста

Для целей бенчмаркинга я пытаюсь настроить 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?

4b9b3361

Ответ 1

TL; DR

Вы (в частности, ваш процессор) не можете извлечь выгоду из 1 ГБ страниц в этом сценарии, но ваш код верен без изменений в системах, которые могут.

Длинная версия

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

My System: Intel Core i7-4700MQ, 32GB RAM 1600MHz, Chipset H87
  • svn co https://github.com/ManuelSelva/c4fun.git
  • cd c4fun.git/trunk
  • make. Обнаружено несколько зависимостей. Установили их. Строка не удалась, но mem_load сделал сборку и ссылку, поэтому не преследовал остальных.
  • Перезагрузите систему, добавив в GRUB время к аргументам загрузки следующее:

    hugepagesz=1G hugepages=10 default_hugepagesz=1G
    

    который резервирует 10 1 ГБ страниц.

  • cd c4fun.git/trunk/mem_load
  • Повторите несколько тестов, используя memload, в режиме шаблона произвольного доступа и привязывая его к ядру 3, что не является 0 (процессор начальной загрузки).

    • ./mem_load -a rand -c 3 -m 1073741824 -i 1048576

      Это привело к приблизительно нулевым промахам TLB.

    • ./mem_load -a rand -c 3 -m 10737418240 -i 1048576

      Это привело к примерно 60% промахов TLB. На догадку я сделал

    • ./mem_load -a rand -c 3 -m 4294967296 -i 1048576

      Это привело к примерно нулевым промахам TLB. На догадку я сделал

    • ./mem_load -a rand -c 3 -m 5368709120 -i 1048576

      Это привело к примерно 20% промахов TLB.

В этот момент я загрузил утилиту cpuid. Это дало мне это для cpuid -1 | grep -i tlb:

   cache and TLB information (2):
      0x63: data TLB: 1G pages, 4-way, 4 entries
      0x03: data TLB: 4K pages, 4-way, 64 entries
      0x76: instruction TLB: 2M/4M pages, fully, 8 entries
      0xb5: instruction TLB: 4K, 8-way, 64 entries
      0xc1: L2 TLB: 4K/2M pages, 8-way, 1024 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):

Как вы можете видеть, мой TLB имеет 4 записи для 1 ГБ страниц. Это хорошо объясняет мои результаты: для 1 ГБ и 4 ГБ арены, 4 слота TLB полностью достаточны, чтобы удовлетворить все обращения. Для 5-гигабайтных аренов и режима шаблонов произвольного доступа 4 из 5 страниц могут отображаться только через TLB, поэтому преследование указателя на оставшееся приведет к промаху. Вероятность преследования указателя на неотображаемой странице равна 1/5, поэтому мы ожидаем, что процент промаха составляет 1/5 = 20%, и мы получим это. Для 10 ГБ отображаются 4/10 страницы, а 6/10 не так, что пропускная способность будет 6/10 = 60%, и мы получили это.

Таким образом, ваш код работает без изменений в моей системе. Тогда ваш код не будет проблематичным.

Затем я провел некоторое исследование по CPU-World, и хотя не все процессоры перечислены с данными геометрии TLB, некоторые из них. Единственный, который я видел, точно соответствовал вашей распечатке cpuid (может быть больше) Xeon Westmere-EP X5650; В CPU-World явно не указано, что данные TLB0 имеют записи для 1 ГБ страниц, но говорят, что процессор имеет "1 ГБ поддержки больших страниц".

Затем я сделал больше исследований и, наконец, прибил его. Автор в RealWorldTech делает (по общему признанию, я еще должен найти источник для этого) комментарий без комментариев в обсуждении подсистемы памяти Sandy Bridge. Он читает следующим образом:

После генерации адресов uops будут обращаться к DTLB для перевода с виртуального на физический адрес параллельно с началом доступа к кешу. DTLB был в основном сохранен, но поддержка 1 ГБ страниц улучшилась. Ранее Westmere добавила поддержку 1 ГБ страниц, но фрагментировала 1 ГБ страниц на многие 2 МБ страницы, так как у TLB не было записей на 1 ГБ страницы. Sandy Bridge добавляет 4 выделенных ввода для 1 ГБ страниц в DTLB.

(добавлен акцент)

Заключение

Какая бы туманная концепция "CPU поддерживает 1GB-страницы", Intel считает, что она не подразумевает, что "TLB поддерживает записи на 1 ГБ". Я боюсь, что вы не сможете использовать 1 ГБ страниц на процессоре Intel Westmere, чтобы уменьшить количество пропусков TLB.

Это, или Intel обманывает нас, выделяя огромные страницы (в TLB) с больших страниц.