
Целью серии экспериментов, выполненных с помощью утилиты NCRB, является измерение пропускной способности DRAM-шины при доступе со стороны центрального процессора. В отличие от ранее выполненного исследования кэш-памяти, на графиках производительности ОЗУ полезную информацию несут пологие горизонтальные участки, имеющие место при обмене информацией объемом более, чем 4 МБ — то есть после завершения переходных процессов, обусловленных влиянием кэш-памяти последнего уровня.
Для корректной интерпретации полученных результатов, приведем расчет лимита пропускной способности оперативной памяти. Работы ведутся на ноутбуке ASUS X570ZD, оснащенном центральным процессором AMD Ryzen 7 2700U, в составе которого имеется графический процессор Radeon RX Vega 10 (кодовое название gfx902). У ноутбука на компонентной стороне есть два SODIMM разъема для установки модулей памяти, соответствующей спецификации DDR4. Для утилизации двухканального режима, обеспечивающего максимальную производительность обмена с ОЗУ, возьмем два модуля Kingston KVR24S17S8/8 типа PC4-2400 с показателем CL=17; объем каждого 8 ГБ с одноранковой организацией.
Итого, максимальная эффективная тактовая частота передачи данных на DRAM-шине составляет 2.4 ГГц; ширина канала передачи данных — 8 байт (64-бит). Для двух каналов получаем
2.4 * 8 * 2 = около 38.4 GBPS
AVX256 vs SSE128
Теоретически, шина оперативной памяти с пропускной способностью около 38,4 гигабайт в секунду должна нивелировать зависимость результата от набора процессорных инструкций. К примеру, адресуя кэш-память первого уровня в многопоточных тестах из предыдущей публикации, мы получали значения скорости более 400 GBPS, при этом, несмотря на жесткий тайминг L1, различия между вариантами SSE128 и AVX256 отсутствовали, в силу известных ограничений векторного тракта процессоров AMD.
Чтение оперативной памяти 128-битными инструкциями SSE восемью потоками;
скорость в установившемся режиме около 32 GBPS
Чтение оперативной памяти 256-битными инструкциями AVX восемью потоками;
скорость в установившемся режиме около 33,5 GBPS
Сравнение 128-битных и 256-битных векторных инструкций в тесте DRAM не принесло сенсации, тем не менее, учитывая выше обозначенные теоретические предпосылки, даже небольшая разница в пользу AVX заслуживает анализа.
- В измерительном цикле SSE-теста, каждая 128-битная инструкция MOVAPD предписывает передать 16 байт между XMM-регистром и оперативной памятью.
- В измерительном цикле AVX-теста, каждая 256-битная инструкция VMOVAPD предписывает передать 32 байта между YMM-регистром и оперативной памятью.
Во втором случае аналогичное количество процессорных команд несет информацию о вдвое большем количестве DRAM-транзакций. Не влияет ли это на эффективность механизмов опережающей выборки, от которых существенно зависит производительность DRAM?
Вместе с тем, природа обнаруженного эффекта скорее косвенная. Дизайн измерительного цикла для 128 и 256-битных операций и выбор дистанции для опережающей загрузки (prefetch distance) несколько различаются в силу различного количества информации, передаваемого одной инструкцией. Кроме того, для операций записи при тех же условиях выигрыш от применения AVX по сравнению с SSE отсутствует. Некэшируемая запись, как известно, не подразумевает опережающей загрузки данных.
Однопоточность
Производительность оперативной памяти, близкая к теоретическим лимитам, достигается лишь в многопоточных тестах.
Чтение оперативной памяти 128-битными инструкциями SSE, один поток;
скорость в установившемся режиме около 25 GBPS
Факт, заслуживающий внимание специалистов по оптимизации программного обеспечения, — в сравнении с рассмотренным выше 8-потоковым сценарием, обеспечившим полную монополизацию процессора, уменьшение количества потоков до одного, оказало влияние не только на абсолютное значение скорости, но и стабильность графика.
SSE128 vs MOV64
Кратная разница в скорости записи с применением векторных 128-битных расширений SSE и x86-инструкции MOV в 64-битной форме, на первый взгляд, неожиданна. Такое падение скорости вдвойне нетипично для процессоров AMD, сильной стороной которых является «консервативный софт».
Объяснение можно найти, если вспомнить, что в современных тестовых сценариях, построенных на основе 128- и 256-битных функциональных расширений SSE и AVX, используется non-temporal hints — технология управления кэш-памятью, позволяющая предотвратить кэширование, снижающее в случае теста ОЗУ производительность, поскольку программа оперирует блоками информации, объем которых многократно превышает объем кэш.
Запись в оперативную память 128-битными SSE-инструкциями, 4 потока.
Инструкция MOVNTPD обеспечивает подавление кэширования,
скорость в установившемся режиме более 35 GBPS
Тест на основе инструкции MOV, напротив, построен на основе консервативного подхода, предполагающего кэширование содержимого ОЗУ по умолчанию и невмешательство программного обеспечения в этот процесс. Как следствие, заполнение кэш-строк из области памяти, в которую выполняется запись приводит к дополнительным операциям чтения, значит, трафик DRAM-шины непроизводительно удваивается. Как результат — запись в DRAM на классических x64 инструкциях кратно медленнее чтения.
Запись в оперативную память 64-битными инструкциями MOV, 4 потока.
Используется кэширование по умолчанию,
скорость в установившемся режиме около 13 GBPS
В рассмотренной ситуации, при записи массива, объем которого кратно превышает объем кэш-памяти последнего уровня, кэширование по умолчанию, характерное для «консервативного софта», драматически снижает производительность. Все просто: процессорные такты на такое кэширование затрачиваются, а его результаты не востребованы. Кроме того, из кэш-памяти вытесняется «более нужная» информация. Вместе с тем, возраст этой проблемы и ее решения на сегодня составляет почти 20 лет, ведь атрибут подавления кэширования non-temporal hint появился еще в процессорах Intel Pentium III в составе набора инструкций SSE.
Если программное обеспечение, написано давно, а потому не использует современные функциональные расширения, но при этом, в соответствии с рекомендациями, прибегает к помощи библиотек операционной системы для копирования и записи больших массивов данных, то оно автоматически получит в свое распоряжение блага non-temporal оптимизации. Ведь периодические обновления ОС, вызывающие состояние аффекта у пользователей, имеют и положительные стороны. Итак, сознаемся, в измерительном сценарии с записью посредством инструкции MOV мы промоделировали ситуацию «экстремально консервативного софта», что в общем-то и не редкость.
Любопытно, что в ряде случаев применения векторных расширений SSE/AVX (а значит — явного управления кэшированием) проявляется более неожиданный факт — запись быстрее чтения.
Виной тому может быть парадокс «квазинекэшируемого чтения», а описанную зависимость результатов от выбора процессорных инструкций можно рассматривать, как аргумент в пользу (но это пока неточно!) данной гипотезы.
Данный феномен, в отличие от ранее рассмотренной ситуации с замедлением записи вследствие нежелательного кэширования, напротив, характерен для бенчмарок современного программного обеспечения, берущего под контроль низкоуровневые аспекты политики доступа к оперативной памяти. В ряде случаев уровень его проявления зависит от так называемой prefetch дистанции и оптимальности ее выбора для конкретной модели процессора. Prefetch дистанция — это разность адресов двух областей памяти: читаемой в данный момент и подвергаемой заблаговременной выборке.
Неоптимальное значение этого параметра делает операцию опережающей выборки менее полезной или вредной:
- занижение prefetch дистанции приведет к тому, что программной предвыборке будет подвергнута информация, которая и без того подвергается аппаратной предвыборке;
- завышение prefetch дистанции приведет к тому, что вместо информации, которая требуется процессору в ближайшее время, будет загружена информация, которая потребуется нескоро, значит — латентность доступа к актуальным данным не будет нивелирована.
Софт и физическая топология платформы
Реализованный тестовый сценарий позволяет оценить характеристики оперативной памяти, имеющие место при доступе к DRAM со стороны центрального процессора. Здесь уместно терминологическое отступление: «Доступ со стороны центрального процессора» в контексте настоящей публикации означает только такие операции чтения и записи оперативной памяти, которые сопровождают выполнение программы x86-ядром (вернее, ядрами) CPU.
Но физически DRAM-контроллер является частью микросхемы CPU, поэтому все обращения к оперативной памяти, инициированные периферийными bus-master устройствами, в том числе реализованными в виде отдельных микросхем и подключенных к портам PCI Express, также обслуживаются DRAM-контроллером CPU.
Для обращений к памяти со стороны таких устройств, а также для bus-master транзакций интегрированного GPU, центральный процессор, как топологическая единица, является участником операции, при этом набор логических процессорных x86-ядер не является ее участником и не влияет на ее тайминги никаким образом, кроме фактора конкурентного доступа к DRAM-шине, что возможно станет темой отдельного исследования…