2015-01-14 2 views
18

Edit: Я обновил свой вопрос с деталями моего тестаКак использовать страницы 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 представляет огромные страницы, выделенные ТНР Befo повторно останавливая его.

На этом этапе мы можем думать, что все в порядке, но, к сожалению, моя скамейка заставляет меня думать, что используется много страниц 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?

+1

Вы можете использовать 'mmap (..., MAP_ANON | MAP_HUGETLB)'? – abligh

+0

@abligh с ошибкой «Не удается выделить память» –

+0

У вас есть огромная поддержка страниц, скомпилированная в ваше ядро? – abligh

ответ

18

TL; DR

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

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

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

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

    hugepagesz=1G hugepages=10 default_hugepagesz=1G 
    

    , который оставляет за 10 1Гб страниц.

  5. cd c4fun.git/trunk/mem_load
  6. Ran несколько тестов с использованием 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. Он читает as follows:

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

(Выделено)

Заключения

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

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

+2

Спасибо за ваши исследования и ответ, и спасибо stackoverflow ;-) –