В каких случаях большие страницы могут ускорить работу?

StackOverflow https://stackoverflow.com/questions/2876377

Вопрос

Современные процессоры x86 способны поддерживать размеры страниц большего размера, чем устаревшие 4K (т. е. 2 МБ или 4 МБ), а также имеются возможности ОС (Линукс, Окна) для доступа к этой функции.

В приведенной выше ссылке Microsoft говорится, что большие страницы «повышают эффективность буфера трансляции, что может повысить производительность часто используемой памяти».Это не очень помогает предсказать, улучшат ли большие страницы ту или иную ситуацию.Меня интересуют конкретные, желательно количественные примеры того, как перемещение некоторой программной логики (или всего приложения) на использование огромных страниц привело к некоторому повышению производительности.У кого-нибудь есть истории успеха?

Я знаю один конкретный случай сам:использование огромных страниц может резко сократить время, необходимое для разветвления большого процесса (предположительно, поскольку количество записей TLB, требующих копирования, уменьшается примерно в 1000 раз).Меня интересует, могут ли огромные страницы принести пользу в менее экзотических сценариях.

Это было полезно?

Решение 2

Я попытался придумать некоторый код, который бы максимально эффективно использовал TLB со страницами по 4 КБ, чтобы изучить возможные выгоды от больших страниц.Материал ниже работает в 2,6 раза быстрее (чем страницы 4 КБ), когда страницы размером 2 МБ предоставляются malloc libhugetlbfs (Intel i7, 64-битный Debian Lenny);надеюсь, очевидно, что scoped_timer и random0n делать.

  volatile char force_result;

  const size_t mb=512;
  const size_t stride=4096;
  std::vector<char> src(mb<<20,0xff);
  std::vector<size_t> idx;
  for (size_t i=0;i<src.size();i+=stride) idx.push_back(i);
  random0n r0n(/*seed=*/23);
  std::random_shuffle(idx.begin(),idx.end(),r0n);

  {
    scoped_timer t
      ("TLB thrash random",mb/static_cast<float>(stride),"MegaAccess");
    char hash=0;
    for (size_t i=0;i<idx.size();++i) 
      hash=(hash^src[idx[i]]);
    force_result=hash;
  }

Более простая «прямая» версия, включающая всего лишь hash=hash^src[i] только 16% прибыли от больших страниц, но (дикие предположения) Intel необычное оборудование предварительной загрузки может помочь в случае с 4K, когда доступ предсказуем (полагаю, я мог бы отключить предварительную выборку выяснить, правда ли это).

Другие советы

Самая большая разница в производительности будет наблюдаться, когда вы осуществляете произвольный доступ к большой области памяти с большим интервалом, где «большой» означает намного больший, чем диапазон, который может быть отображен всеми небольшими записями страниц в TLB (которые обычно имеют несколько уровней в современных процессорах).

Еще больше усложняет ситуацию то, что количество записей TLB для страниц размером 4 КБ часто превышает количество записей для страниц размером 2 МБ, но это сильно зависит от процессора.Существует также множество различий в том, сколько записей «большой страницы» доступно в TLB уровня 2.

Например, в системе AMD Opteron Family 10h Revision D («Стамбул») cpuid сообщает:

  • L1 ДТЛБ:Страницы по 4 КБ:48 записей;Страницы по 2 МБ:48 записей;Страницы по 1 ГБ:48 записей
  • L2 TLB:Страницы по 4 КБ:512 записей;Страницы по 2 МБ:128 записей;Страницы по 1 ГБ:16 записей

В системе Intel Xeon 56xx («Westmere») cpuid сообщает:

  • L1 ДТЛБ:Страницы по 4 КБ:64 записи;Страницы по 2 МБ:32 записи
  • L2 TLB:Страницы по 4 КБ:512 записей;Страницы по 2 МБ:никто

Оба могут отображать 2 МБ (512*4 КБ) с использованием небольших страниц, прежде чем возникнут промахи TLB уровня 2, в то время как система Westmere может отображать 64 МБ, используя свои 32 записи TLB по 2 МБ, а система AMD может отображать 352 МБ, используя 176 записей TLB по 2 МБ в своих L1 и L2. TLB.Любая система получит значительное ускорение за счет использования больших страниц для произвольного доступа в диапазонах памяти, которые намного больше 2 МБ и меньше 64 МБ.Система AMD должна продолжать демонстрировать хорошую производительность при использовании больших страниц для гораздо большего диапазона памяти.

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

  • 5 обращений к памяти для загрузки данных, отображенных на странице размером 4 КБ,
  • 4 обращения к памяти для загрузки данных, отображенных на странице размером 2 МБ, и
  • 3 обращения к памяти для загрузки данных, отображенных на странице размером 1 ГБ.

В каждом случае последнее обращение к памяти предназначено для получения запрошенных данных, тогда как остальные обращения необходимы для получения различных частей информации о переводе страницы.Лучшее описание, которое я видел, находится в разделе 5.3 «Руководства программиста по архитектуре AMD64, том 2» AMD:Системное программирование» (публикация 24593) http://support.amd.com/us/Embedded_TechDocs/24593.pdf

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

Заметка 2:К сожалению, даже знания такого уровня детализации недостаточно, поскольку все современные процессоры имеют дополнительные кэши для верхних уровней иерархии перевода страниц.Насколько я могу судить, они очень плохо документированы публично.

Я видел улучшения в некоторых сценариях HPC/Grid, особенно в пакетах физики с очень, очень большими моделями на машинах с большим количеством оперативной памяти.Кроме того, на машине был единственным активным процессом запуска модели.Я подозреваю, хотя и не измерял, что некоторые функции БД (например.оптовый импорт) также выиграют.

Лично я думаю, что если у вас нет очень хорошо профилированного/понятного профиля доступа к памяти и он не выполняет большой объем доступа к памяти, маловероятно, что вы увидите какое-либо существенное улучшение.

Это становится эзотерическим, но огромные страницы TLB существенно меняют архитектуру Intel Xeon Phi (MIC) при передаче памяти DMA (от хоста к Phi через PCIe). Эта ссылка Intel описывает, как включить огромные страницы..Я обнаружил, что увеличение размера передачи DMA сверх 8 МБ при обычном размере страницы TLB (4 КБ) начало снижать производительность примерно с 3 ГБ/с до менее 1 ГБ/с, как только размер передачи достиг 512 МБ.

После включения огромных страниц TLB (2 МБ) скорость передачи данных продолжала увеличиваться до более чем 5 ГБ/с для передачи DMA объемом 512 МБ.

Я получаю ускорение примерно на 5% на серверах с большим объемом памяти (>=64 ГБ), на которых выполняются большие процессы.напримердля Java-процесса размером 16 ГБ это страницы размером 4 М x 4 КБ, но только страницы размером 4 КБ x 4 МБ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top