Какие подходы применяемые в архитектурах компьютеров позволяли повысить их производительность

Обновлено: 07.07.2024

Компьютеры, даже персональные, становятся все сложнее. Не так уж давно в гудящем на столе ящике все было просто — чем больше частота, тем больше производительность. Теперь же системы стали многоядерными, многопроцессорными, в них появились специализированные ускорители, компьютеры все чаще объединяются в кластеры.
Зачем? Как во всем этом многообразии разобраться?
Что значит SIMD, SMP, GPGPU и другие страшные слова, которые встречаются все чаще?
Каковы границы применимости существующих технологий повышения производительности?

Введение

Откуда такие сложности?

Компьютерные мощности быстро растут и все время кажется, что все, существующей скорости хватит на все.
Но нет — растущая производительность позволяет решать проблемы, к которым раньше нельзя было подступиться. Даже на бытовом уровне есть задачи, которые загрузят ваш компьютер надолго, например кодирование домашнего видео. В промышленности и науке таких задач еще больше: огромные базы данных, молекулярно-динамические расчеты, моделирование сложных механизмов — автомобилей, реактивных двигателей, все это требует возрастающей мощности вычислений.
В предыдущие годы основной рост производительности обеспечивался достаточно просто, с помощью уменьшения размеров элементов микропроцессоров. При этом падало энергопотребление и росли частоты работы, компьютеры становились все быстрее, сохраняя, в общих чертах, свою архитектуру. Менялся техпроцесс производства микросхем и мегагерцы вырастали в гигагерцы, радуя пользователей возросшей производительностью, ведь если «мега» это миллион, то «гига» это уже миллиард операций в секунду.
Но, как известно, рай бывает либо не навсегда, либо не для всех, и не так давно он в компьютерном мире закончился. Оказалось, частоту дальше повышать нельзя — растут токи утечки, процессоры перегреваются и обойти это не получается. Можно, конечно, развивать системы охлаждения, применять водные радиаторы или совсем уж жидким азотом охлаждать — но это не для каждого пользователя доступно, только для суперкомпьютеров или техноманьяков. Да и при любом охлаждении возможность роста была небольшой, где-то раза в два максимум, что для пользователей, привыкших к геометрической прогрессии, было неприемлемо.
Казалось, что закон Мура, по которому число транзисторов и связанная с ним производительность компьютеров удваивалась каждые полтора-два года, перестанет действовать.
Пришло время думать и экспериментировать, вспоминая все возможные способы увеличения скорости вычислений.

Формула производительности

Возьмем самую общую формулу производительности:


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


Первая часть полученного произведения — количество инструкций, выполняемых за один такт (IPC, Instruction Per Clock), вторая — количество тактов процессора в единицу времени, тактовая частота.
Таким образом, для увеличения производительности нужно или поднимать тактовую частоту или увеличивать количество инструкций, выполняемых за один такт.
Т.к. рост частоты остановился, придется увеличивать количество исполняемых «за раз» инструкций.

Включаем параллельность

Как же увеличить количество инструкций, исполняемых за один такт?
Очевидно, выполняя несколько инструкций за один раз, параллельно. Но как это сделать?
Все сильно зависит от выполняемой программы.
Если программа написана программистом как однопоточная, где все инструкции выполняются последовательно, друг за другом, то процессору (или компилятору) придется «думать за человека» и искать части программы, которые можно выполнить одновременно, распараллелить.

Параллелизм на уровне инструкций

Возьмем простенькую программу:
a = 1
b = 2
c = a + b

Первые две инструкции вполне можно выполнять параллельно, только третья от них зависит. А значит — всю программу можно выполнить за два шага, а не за три.
Процессор, который умеет сам определять независимые и непротиворечащие друг другу инструкции и параллельно их выполнять, называется суперскалярным.
Очень многие современные процессоры, включая и последние x86 — суперскалярные процессоры, но есть и другой путь: упростить процессор и возложить поиск параллельности на компилятор. Процессор при этом выполняет команды «пачками», которые заготовил для него компилятор программы, в каждой такой «пачке» — набор инструкций, которые не зависят друг от друга и могут исполняться параллельно. Такая архитектура называется VLIW (very long instruction word — «очень длинная машинная команда»), её дальнейшее развитие получило имя EPIC (explicitly parallel instruction computing) — микропроцессорная архитектура с явным параллелизмом команд)
Самые известные процессоры с такой архитектурой — Intel Itanium.
Есть и третий вариант увеличения количества инструкций, выполняемых за один такт, это технология Hyper Threading В этой технологии суперскалярный процессор самостоятельно распараллеливает не команды одного потока, а команды нескольких (в современных процессорах — двух) параллельно запущенных потоков.
Т.е. физически процессорное ядро одно, но простаивающие при выполнении одной задачи мощности процессора могут быть использованы для выполнения другой. Операционная система видит один процессор (или одно ядро процессора) с технологией Hyper Threading как два независимых процессора. Но на самом деле, конечно, Hyper Threading работает хуже, чем реальные два независимых процессора т.к. задачи на нем будут конкурировать за вычислительные мощности между собой.

Технологии параллелизма на уровне инструкций активно развивались в 90е и первую половину 2000х годов, но в настоящее время их потенциал практически исчерпан. Можно переставлять местами команды, переименовывать регистры и использовать другие оптимизации, выделяя из последовательного кода параллельно исполняющиеся участки, но все равно зависимости и ветвления не дадут полностью автоматически распараллелить код. Параллелизм на уровне инструкций хорош тем, что не требует вмешательства человека — но этим он и плох: пока человек умнее микропроцессора, писать по-настоящему параллельный код придется ему.

Параллелизм на уровне данных

Векторные процессоры

Мы уже упоминали скалярность, но кроме скаляра есть и вектор, и кроме суперскалярных процессоров есть векторные.
Векторные процессоры выполняют какую-то операцию над целыми массивами данных, векторами. В «чистом» виде векторные процессоры применялись в суперкомьютерах для научных вычислений в 80-е годы.
По классификации Флинна, векторные процессоры относятся к SIMD — (single instruction, multiple data — одиночный поток команд, множественный поток данных).
В настоящее время в процессорах x86 реализовано множество векторных расширений — это MMX, 3DNow!, SSE, SSE2 и др.
Вот как, например, выглядит умножение четырех пар чисел одной командой с применением SSE:

float a[4] = < 300.0, 4.0, 4.0, 12.0 >;
float b[4] = < 1.5, 2.5, 3.5, 4.5 >;
__asm movups xmm0, a ; // поместить 4 переменные с плавающей точкой из a в регистр xmm0
movups xmm1, b ; // поместить 4 переменные с плавающей точкой из b в регистр xmm1
mulps xmm1, xmm0 ; // перемножить пакеты плавающих точек: xmm1=xmm1*xmm0
movups a, xmm1 ; // выгрузить результаты из регистра xmm1 по адресам a
>;

Таким образом, вместо четырех последовательных скалярных умножений мы сделали только одно — векторное.
Векторные процессоры могут значительно ускорить вычисления над большими объемами данных, но сфера их применимости ограничена, далеко не везде применимы типовые операции над фиксированными массивами.
Впрочем, гонка векторизации вычислений далеко не закончена — так в последних процессорах Intel появилось новое векторное расширение AVX (Advanced Vector Extension)
Но гораздо интереснее сейчас выглядят

Графические процессоры


Теоретическая вычислительная мощность процессоров в современных видеокартах растет гораздо быстрее, чем в обычных процессорах (посмотрим знаменитую картинку от NVIDIA)

Не так давно эта мощность была приспособлена для универсальных высокопроизводительных вычислений с помощью CUDA/OpenCL.
Архитектура графических процессоров (GPGPU, General Purpose computation on GPU – универсальные расчеты средствами видеокарты), близка к уже рассмотренной SIMD.
Она называется SIMT — (single instruction, multiple threads, одна инструкция — множество потоков). Так же как в SIMD операции производятся с массивами данных, но степеней свободы гораздо больше — для каждой ячейки обрабатываемых данных работает отдельная нить команд.
В результате
1) Параллельно могут выполняться сотни операций над сотнями ячеек данных.
2) В каждом потоке выполняется произвольная последовательность команд, она может обращаться к разным ячейкам.
3) Возможны ветвления. При этом, правда, параллельно могут выполняться только нити с одной и той же последовательностью операций.

GPGPU позволяют достичь на некоторых задачах впечатляющих результатов. но существуют и принципиальные ограничения, не позволяющие этой технологии стать универсальной палочкой-выручалочкой, а именно
1) Ускорить на GPU можно только хорошо параллелящийся по данным код.
2) GPU использует собственную память. Трансфер данных между памятью GPU и памятью компьютера довольно затратен.
3) Алгоритмы с большим количеством ветвлений работают на GPU неэффективно

Мультиархитектуры-

Итак, мы дошли до полностью параллельных архитектур — независимо параллельных и по командам, и по данным.
В классификации Флинна это MIMD (Multiple Instruction stream, Multiple Data stream — Множественный поток Команд, Множественный поток Данных).
Для использования всей мощности таких систем нужны многопоточные программы, их выполнение можно «разбросать» на несколько микропроцессоров и этим достичь увеличения производительности без роста частоты. Различные технологии многопоточности давно применялись в суперкомпьютерах, сейчас они «спустились с небес» к простым пользователям и многоядерный процессор уже скорее правило, чем исключение. Но многоядерность далеко не панацея.

Суров закон, но это закон

Параллельность, это хороший способ обойти ограничение роста тактовой частоты, но у него есть собственные ограничения.
Прежде всего, это закон Амдала, который гласит
Ускорение выполнения программы за счет распараллеливания её инструкций на множестве вычислителей ограничено временем, необходимым для выполнения её последовательных инструкций.

Ускорение кода зависит от числа процессоров и параллельности кода согласно формуле


Действительно, с помощью параллельного выполнения мы можем ускорить время выполнения только параллельного кода.
В любой же программе кроме параллельного кода есть и последовательные участки и ускорить их с помощью увеличения количества процессоров не получится, над ними будет работать только один процессор.


Например, если выполнение последовательного кода занимает всего 25% от времени выполнения всей программы, то ускорить эту программу более чем в 4 раза не получится никак.
Давайте построим график зависимости ускорения нашей программы от количества параллельно работающих вычислителей-процессоров. Подставив в формулу 1/4 последовательного кода и 3/4 параллельного, получим

Грустно? Еще как.
Самый быстрый в мире суперкомпьютер с тысячами процессоров и терабайтами памяти на нашей, вроде бы даже неплохо (75%!) параллелящейся задаче, меньше чем вдвое быстрее обычного настольного четырехядерника.
Причем всё еще хуже, чем в этом идеальном случае. В реальном мире затраты обеспечение параллельности никогда не равны нулю и потому при добавлении все новых и новых процессоров производительность, начиная с некоторого момента, начнет падать.
Но как же тогда используется мощь современных очень-очень многоядерных суперкомпьютеров?
Во многих алгоритмах время исполнения параллельного кода сильно зависит от количества обрабатываемых данных, а время исполнения последовательного кода — нет. Чем больше данных требуется обработать, тем больше выигрыш от параллельности их обработки. Потому «загоняя» на суперкомп большие объемы данных получаем хорошее ускорение.
Например перемножая матрицы 3*3 на суперкомпьютере мы вряд ли заметим разницу с обычным однопроцессорным вариантом, а вот умножение матриц, размером 1000*1000 уже будет вполне оправдано на многоядерной машине.
Есть такой простой пример: 9 женщин за 1 месяц не могут родить одного ребенка. Параллельность здесь не работает. Но вот та же 81 женщина за 9 месяцев могут родить (берем максимальную эффективность!) 81 ребенка, т.е.получим максимальную теоретическую производительность от увеличения параллельности, 9 ребенков в месяц или, в среднем, тот же один ребенок в месяц на 9 женщин.
Большим компьютерам — большие задачи!

Мультипроцессор

Мультипроцессор — это компьютерная система, которая содержит несколько процессоров и одно видимое для всех процессоров. адресное пространство.
Мультипроцессоры отличаются по организации работы с памятью.

Системы с общей памятью


В таких системах множество процессоров (и процессорных кэшей) имеет доступ к одной и той же физической оперативной памяти. Такая модель часто называется симметричной мультипроцессорностью (SMP). Доступ к памяти при таком построении системы называется UMA (uniform memory access, равномерный доступ) т.к. любой процессор может обратиться к любой ячейке памяти и скорость этого обращения не зависит от адреса памяти. Однако каждый микропроцессор может использовать свой собственный кэш.

Несколько подсистем кэш-памяти процессоров, как правило, подключены к общей памяти через шину

Посмотрим на рисунок.
Что у нас хорошего?
Любой процессор обращается ко всей памяти и вся она работает одинаково. Программировать для таких систем проще, чем для любых других мультиархитектур. Плохо то, что все процессоры обращаются к памяти через шину, и с ростом числа вычислительных ядер пропускная способность этой шины быстро становится узким местом.
Добавляет головной боли и проблема обеспечения когерентности кэшей.

Когерентность кэша

Допустим, у нас есть многопроцессорный компьютер. Каждый процессор имеет свой кэш, ну, как на рисунке вверху. Пусть некоторую ячейку памяти читали несколько процессоров — и она попала к ним в кэши. Ничего страшного, пока это ячейка неизменна — из быстрых кэшей она читается и как-то используется в вычислениях.
Если же в результате работы программы один из процессоров изменит эту ячейку памяти, чтоб не было рассогласования, чтоб все остальные процессоры «видели» это обновление придется изменять содержимое кэша всех процессоров и как-то тормозить их на время этого обновления.
Хорошо если число ядер/процессоров 2, как в настольном компьютере, а если 8 или 16? И если все они обмениваются данными через одну шину?
Потери в производительности могут быть очень значительные.

Многоядерные процессоры


Как бы снизить нагрузку на шину?
Прежде всего можно перестать её использовать для обеспечения когерентности. Что для этого проще всего сделать?
Да-да, использовать общий кэш. Так устроены большинство современных многоядерных процессоров.

Посмотрим на картинку, найдем два отличия от предыдущей.
Да, кэш теперь один на всех, соответственно, проблема когерентности не стоит. А еще круги превратились в прямоугольники, это символизирует тот факт, что все ядра и кэши находятся на одном кристалле. В реальной действительности картинка несколько сложнее, кэши бывают многоуровневыми, часть общие, часть нет, для связи между ними может использоваться специальная шина, но все настоящие многоядерные процессоры не используют внешнюю шину для обеспечения когерентности кэша, а значит — снижают нагрузку на нее.
Многоядерные процессоры — один из основных способов повышения производительности современных компьютеров.
Уже выпускаются 6 ядерные процессоры, в дальшейшем ядер будет еще больше… где пределы?
Прежде всего «ядерность» процессоров ограничивается тепловыделением, чем больше транзисторов одновременно работают в одном кристалле, тем больше этот кристалл греется, тем сложнее его охлаждать.
А второе большое ограничение — опять же пропускная способность внешней шины. Много ядер требуют много данных, чтоб их перемалывать, скорости шины перестает хватать, приходится отказываться от SMP в пользу

NUMA (Non-Uniform Memory Access — «неравномерный доступ к памяти» или Non-Uniform Memory Architecture — «Архитектура с неравномерной памятью») — архитектура, в которой, при общем адресном пространстве, скорость доступа к памяти зависит от ее расположения Обычно у процессора есть " своя" память, обращение к которой быстрее и «чужая», доступ к которой медленнее.
В современных системах это выглядит примерно так


Процессоры соединены с памятью и друг с другом с помощью быстрой шины, в случае AMD это Hyper Transport, в случае последних процессоров Intel это QuickPath Interconnect
Т.к. нет общей для всех шины то, при работе со «своей» памятью, она перестает быть узким местом системы.
NUMA архитектура позволяет создавать достаточно производительные многопроцессорные системы, а учитывая многоядерность современных процессоров получим уже очень серьезную вычислительную мощность «в одном корпусе», ограниченную в основном сложностью обеспечения кэш-когерентности этой путаницы процессоров и памяти.
Но если нам нужна еще большая мощность, придется объединять несколько мультипроцессоров в

Мультикомпьютер

Сводим все воедино

Ну вот, вкратце пробежались почти по всем технологиям и принципам построения мощных вычислительных систем.
Теперь есть возможность представить себе строение современного суперкомпьютера.
Это мультикомпьютер-кластер, каждый узел которого — NUMA или SMP система с несколькими процессорами, каждый из процессоров с несколькими ядрами, каждое ядро с возможностью суперскалярного внутреннего параллелизма и векторными расширениями. Вдобавок ко всему этому во многих суперкомпьютерах установлены GPGPU — ускорители.
У всех этих технологий есть плюсы и ограничения, есть тонкости в применении.
А теперь попробуйте эффективно загрузить-запрограммировать всё это великолепие!
Задача нетривиальная… но очень интересная.
Что-то будет дальше?

Производительности процессора много не бывает. Всегда можно найти программу, которая сможет утилизировать всю мощь CPU, и даже «попросит добавка».

Если в системе установлен не самый мощный процессор, поддерживаемый материнской платой, можно купить более производительный CPU. Но обычно это дорого и, относительно современных устройств, не даст сколь-либо заметного буста. Что же в таком случае можно придумать?

1. Поменять систему охлаждения

Последние поколения многоядерных процессоров имеют весьма горячий нрав.

В случае Intel, проблема в старом 14нм техпроцессе. Микроархитектура (даже актуальное поколение, фактически, тот же Skylake 2015го года с увеличенным числом ядер, кэшем и небольшими изменениями) выжата практически до предела.

У AMD проблема другая: чиплетная компоновка приводит к неравномерному тепловыделению на поверхности крышки, а уменьшение техпроцесса (последние два поколения выпускаются по 7нм техпроцессу) уменьшает площадь, с которой отводится тепло. В результате, кулеры оказываются менее эффективны, нежели при одном кристалле, расположенном точно в центре.

Добавим сюда турбобуст (автоматическое повышение частоты), включающийся при подаче какой-либо нагрузки на CPU.

И что же выходит? Боксовый (идущий в комплекте с процессором) кулер, равно как и прочие маломощные модели, не смогут в полной мере раскрыть потенциал процессора. Покупка хорошей «башни» или системы жидкостного охлаждения поможет CPU работать на максимуме возможностей. Если, конечно, позволит материнская плата.

2. Замена материнской платы

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

4 фаз питания мало для полноценной работы 10-ядерного Intel Core i9-10900K, учитывая его весьма высокое энергопотребление. Самый вероятный сценарий подобного тандема — троттлинг по питанию; фазы будут перегреваться и автоматика снизит частоту процессора.

Мощному процессору просто необходима хорошая материнская плата.

3. Разгон CPU

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

4. Разгон памяти

Для одноядерных приложений разгон ОЗУ часто давал преимущество, близкое к погрешности. Всё изменилось с приходом многоядерных программ, которым нужно активно обмениваться памятью между потоками.

В случае процессоров AMD всё ещё интереснее. Частота внутренней шины Infinity Fabric, через которую осуществляется взаимодействие узлов CPU, привязана к частоте оперативной памяти. Следовательно, можно увеличить производительность процессора просто подняв частоту ОЗУ.

5. Замена памяти

Актуально, если используемая память имеет высокую латентность, низкую частоту, или просто установлена одна планка ОЗУ. В последнем случае можно купить ещё одну планку, желательно с теми же характеристиками, что и установленная.

Программы загружаются в оперативную память, откуда передаются на исполнение процессором. Следовательно, чем быстрее ОЗУ «откликается» на запросы CPU, тем быстрее будет выполняться программа.

В случае использования многоканального режима (в настольных процессорах пока что стандартом является двухканальный режим) увеличивается пропускная способность ОЗУ, что опять же положительным образом сказывается на производительности многопоточных приложений.

6. Сменить корпус компьютера

Здесь очевидно: использование корпуса с плохой продуваемостью приводит к скапливанию тёплого (а потом и горячего) воздуха внутри системного блока. Если температура внутри переваливает за 70 градусов, толку будет мало даже от замены кулера на самую дорогую «башню».

7. Андервольтинг

Понижение потребляемого CPU напряжения снизит выделяемое тепло, что при прочих равных может дать небольшую прибавку к частоте процессора. Но тут многое зависит от доставшегося экземпляра процессора. Работай все CPU одинаково, не было бы смысла в моделях Intel Core i5-10400 и i5-10600 (разница в цене более 30$) или AMD Ryzen 7 3700X и 3800X (разница 70$). Для старших моделей применяются более удачные кристаллы.

Повышение производительности процессоров в большинстве случаев достигается за счет применения технологических и архитектурных решений. Технологические решения: технология производства ИС, повышение тактовой частоты, уменьшение проектной нормы. Архитектурные способы связаны с рядом направлений: оптимизация системы команд с учетом развития технологий программирования, использование методов и средств параллельной обработки данных.

1. конвейеризация – это естественное средство реализации параллелизма линейной последовательности команд. В процессоре команда разбивается на 5–6 ступеней, которые исполняются в различных блоках процессора. Каждый блок в цепочке осуществляет только один этап исполнения команды. Полная обработка команды занимает несколько тактов. Выборка (IF) – промежуточный буфер – дешифрация команды (ID)– промежуточный буфер – чтение операции (RD)– промежуточный буфер – исполнение операции (EX)– промежуточный буфер – запись результата (WB).


В ходе выполнения команда продвигается по конвейеру, освобождая ступень для следующей команды. Для хранения информации, передаваемой между ступенями, используются внутренние промежуточные буферы, которые обновляются после каждого такта. Благодаря конвейерной обработке обрабатывается несколько следующих друг за другом команд. Из принципа конвейера следует, что повышение производительности прямо пропорционально количеству ступеней. Однако существуют ситуации, при которых в процессе выполнения происходит временная остановка конвейера, которые называются конфликтами. Конфликты снижают производительность процессора и для уменьшения их отрицательного влияния разрабатывают специальные архитектурные решения. Существует 3 типа конфликтов:

конфликты по ресурсам возникают, когда нескольким командам, находящимся на разных ступенях конвейера требуется использование одного и того же ресурса, например, памяти; конфликт по данным – ситуация, когда или исходный операнд или результат недоступны в положенное время; конфликт по управлению возникает при конвейеризации команд условного перехода и других ситуациях, приводящих к изменению значения счетчика команд.

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

Суперскалярность вычислений.

Означает, что на каждом этапе обрабатывается сразу несколько потоков инструкций. Современные процессоры способны запускать на исполнение не только ту команду, которая стоит на входе, но и следующие за ней.

Внеочередное исполнение команд.

Означает, что операции не обязаны выполняться в устройствах строго в том порядке, в котором определены в коде. Более поздние могут выполняться перед ранними, если не зависят от порождаемых результатов. Процессор должен лишь гарантировать, чтобы результаты внеочередного выполнения совпадали с результатами последовательного.

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

Архитектура процессоров.

Процессорное ядро – конкретное воплощение микроархитектуры, являющееся стандартом для целой серии процессоров. В микроархитектуру входят длина конвейера, разновидности КЭШа и другие общие принципы.

Ядро – это воплощение микроархитектуры в кристалле, обладающее набором характеристик.

Ревизия – модификация ядра, крайне незначительно отличающаяся от предыдущей.

Частота работы ядра – как правило, каждое конкретное ядро может исполнять различное количество команд за один такт. Частота определяет количество тактов. В рамках одного и того же ядра увеличение частоты не всегда пропорционально увеличению производительности. Разные виды частот процессора делают процессоры, которые потом тестируют на частоту, то есть не существует процессора с точным, определенным значением показателя частоты.

12.Принципы взаимодействия процессора и ОП.

Контроллер памяти.

Команды и данные в процессор попадают из ОП. В современных компьютерах процессор как устройство к памяти обращаться не может. Он имеет в своем составе специализированное устройство, называемое контроллер памяти. Контроллер памяти является мостом между ОП и использующими её устройствами. Раньше контроллер памяти входил в состав chipset North Bridge. От его быстродействия во многом зависела скорость обмена данных между процессором и ОП. Процессор с помощью процессорной шины подсоединяется к контроллеру памяти. Также по процессорной шине идет обмен с видеокартой, жестким диском и другими устройствами. У классических процессоров шина одна. В современных процессорах (например, AMD) существует несколько процессорных шин. Некоторые из них работают со всеми устройствами, кроме памяти, а для памяти существует отдельная шина. В данном случае контроллер памяти встроен непосредственно в процессор. Плюсы: сокращение пути между процессором и ОП, но увеличение нагрузки на процессор при обмене с жестким диском или видеокартой с ОП.

Разрядность шины памяти. Вся память имеет 64-разрядную шину, то есть за один такт по шине передается 8 байт. Для шин памяти DDR. Некоторые контроллеры оснащены несколькими контроллерами, передача по которым идет независимо друг от друга. В стандартном процессоре контроллер двуканальный, в продвинутом – трехканальный.

Скорость чтения/записи. Теоретически ограничивается пропускной способностью самой памяти. 8 байт * 2 канала * 2 DDR * 200 МГц = 6,4 Гб.

Латентность. Характеристика, влияющая на фактическую скорость работы процессора с ОП. Латентность – это время, которое требуется для того, чтобы начать считывать информацию с определенного адреса. Чем больше объем памяти, тем больше её латентность.

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций.


Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой.


Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰).


Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого.


Результаты тестов SPECcpu2006 подталкивают к выводу, что самые высокопроизводительные на сегодняшний день ядра микропроцессоров имеют микроархитектуру Sandy Bridge с векторным расширением AVX.

Результаты тестов SPECcpu2006 подталкивают к выводу, что самые высокопроизводительные на сегодняшний день ядра микропроцессоров имеют микроархитектуру Intel Sandy Bridge с векторным расширением AVX.

Современные технологии автоматического распараллеливания позволяют поднимать производительность работы последовательных кодов, и теперь иногда трудно понять — быстрее ли работают появившиеся на рынке процессорные ядра или высокое быстродействие было достигнуто за счет увеличения их числа. В этом смысле, после разрешения применять в тестах автоматическое распараллеливание компиляторами, тесты SPECcpu2006 (табл. 1) перестали быть точной метрикой производительности процессоров при выполнении последовательных программ, с которыми сегодня работает подавляющее большинство пользователей. При этом стало труднее сравнить даже производительность процессоров, поскольку однопроцессорные результаты для серверов уже приводятся не всегда. Например, в случае с Intel Xeon E3 на базе Sandy Bridge сегодня возможны только однопроцессорные версии, а для их конкурентов обычно приводятся лучшие данные для двух и более процессорных систем.

Архитектура для повышения производительности
Таблица 1. Производительность м микропроцессоров

Для 16-ядерных процессоров Opteron 6200 с микроархитектурой Bulldozer, поддерживающей расширение AVX (Advanced Vector Extensions), официальные данные по SPECint2006/SPECfp2006 вообще отсутствуют, представлены лишь данные по SPECint_rate2006/SPECfp_rate2006. По первому показателю один процессор Xeon Е3-1280 опережает два процессора Opteron 6204 (cамая высокочастотная модель с четырьмя ядрами — 3,3 ГГц, в турборежиме — 4,2 ГГц). По показателю SPECfp_rate2006 компьютер с двумя Opteron 6204 и с вдвое большим числом ядер быстрее однопроцессорного E3-1280 в 1,3 раза. Учитывая, что данные rate-тестов почти линейно масштабируются с числом процессоров, можно предположить, что ядра Bulldozer сегодня отстают по производительности от доступных Xeon E3. Имеется отрыв по производительности одиночных ядер и процессоров Xeon E3 относительно Opteron предыдущего поколения. По базовому значению SPECfp2006, как и по SPECint2006, Xeon сильно впереди относительно Power7. Лишь на SPECfp2006 процессоры Power7/3,86 ГГц опережают по пиковому значению E3-1280.

Возможно, на результаты SPECfp_peak2006 сказалось и автораспараллеливание у IBM на 16 ядрах (два процессора) против четырех ядер (один процессор) у Intel. Кроме того, результаты Intel могут быть выше на E3-1290 c более высокой, чем у 1280, тактовой частотой (3,6–4 ГГц при использовании Turbo Boost), не говоря уже об ожидаемых многопроцессорных вариантах Xeon/Sandy Bridge. Но если брать пиковую производительность с плавающей запятой, то Power7 окажется впереди — его максимальная тактовая частота, 4,14 ГГц, чуть выше, чем у E3-1290 (4 ГГц): оба процессора способны выдавать восемь результатов двойной точности за такт. Важно учитывать также отношения стоимость/производительность и, особенно для HPC-приложений, «плотность упаковки», связанную с числом ядер в процессорах (она очень высока в Opteron 6200), а также тепловыделение.

Микроархитектура

Приведенный здесь анализ представляет интерес не только для ознакомления с аппаратными средствами, но и для программистов, в первую очередь на ассемблере. Микроархитектура ядра Sandy Bridge (см. рисунок) была значительно усовершенствована по сравнению с Nehalem [ 1 ], причем наиболее существенным улучшением стало увеличение числа исполнительных устройств (EU) c плавающей запятой. Это привело к тому, что за каждый такт выдается вдвое больше результатов с плавающей запятой (с двойной точностью — восемь). Важным также является поддержка 256-разрядного расширения AVX.

Архитектура для повышения производительности
Общая блок-схема конвейера Sandy Bridge

Во фронтальной части конвейера (обозначим ее как FE) последовательно выбираются команды и декодируются в микрооперации (MOP), обеспечивая их потоком последующие стадии обработки. Соответствующие им блоки микропроцессоров все вместе иногда именуют «исполнительным движком» (Execution Engine, EE). В Sandy Bridge — это суперскалярный (до шести МОР за такт) блок, обеспечивающий внеочередное выполнение МОР. Движок фактически реализует архитектуру потока данных (dataflow) — МОР начинают выполняться, как только становятся готовы исходные операнды и исполнительные ресурсы.

Последние стадии конвейера (после выполнения МОР) реализуются с применением устройства «завершения» (RU, retirement unit), в котором осуществляется обработка исключительных ситуаций выполнения, а результаты делаются «видимыми» в порядке, определяемом исходным кодом программы.

Проведенные в Sandy Bridge усовершенствования в иерархии TLB повышают производительность, в первую очередь для приложений с большим рабочим множеством страниц. I-TLB в Sandy Bridge имеет емкость 128 строк для страниц емкостью 4 Кбайт (как в Nehalem) и восемь строк (против семи в Nehalem) для страниц по 2/4 Мбайт. Емкость D-TLB для страниц размером 4 Кбайт и 2/4 Мбайт составляет 64 и 32 cоответственно; кроме того, D-TLB поддерживает теперь страницы по 1 Гбайт (четыре строки). Буфер D-TLB обеспечивает три преобразования линейного адреса в физический за такт (два для адресов загрузки и одно для адресов записи), что отвечает возможностям одновременного выполнения Sandy Bridge трех соответствующих команд. При промахе в I-TLB или D-TLB обращение идет в общий для команд и данных TLB второго уровня, STLB, емкостью 512 строк для страниц в 4 Кбайт. При промахе в I-TLB/D-TLB и попадании в STLB задержка равна семи тактам.

В FE устройство предсказания переходов (назовем его BPU) указывает на блок кодов программы, который выбирается из кэша декодированных команд (Decoded I-cache, DI-кэш), из I-кэша, из кэшей L2, L3 или из оперативной памяти. При выборке из I-кэша используются традиционные для Intel четыре декодера СISC-команд в МОР, первый из которых декодирует команды, порождающие до четырех МОР, а оставшиеся — по одной МОР. Более сложные CISC-команды используют последовательности МОР, хранящиеся в ROM-кэше.

Декодеры направляют MOP в очередь (MOP туда могут попадать и прямо из DI-кэша) и в DI-кэш. В очереди реализован также детектор циклов (Loop Stream Detector), распознающий циклы длиной не более 28 МОР, целиком размещающиеся в очереди. При обнаружении такого цикла его тело «закрепляется» в очереди МОР. Однако раскрутка (unrolling) циклов обычно более предпочтительна для повышения производительности.

Все декодеры поддерживают микро- и макро-«объединение» (fusion). При микрообъединении несколько МОР одной команды объединяются в одну сложную МОР, что типично для операций работы с памятью. При макрообъединении две команды сливаются в одну МОР. Первая команда из пары устанавливает флаги (например, сравнение), а вторая — условный переход. Микро- и макрообъединение увеличивает, в частности, пропускную способность конвейера.

Применение DI-кэша более эффективно по сравнению с применением обычных стадий декодирования. Благодаря DI-кэшу растет скорость доставки МОР к исполнительным блокам и уменьшается задержка при неправильном предсказании перехода. Емкость DI-кэша составляет 1536 МОР.

EE реализует финальные стадии конвейера и включает устройства переименования регистров/распределения ресурсов, устройство завершения (RU) и планировщик с исполнительными устройствами (EU). Блок EE, по сравнению с Nehalem, был усовершенствован для повышения среднего числа выполняемых за такт команд. Так, с 36 до 54 возросло число строк в планировщике, выросло также число буферов для операций загрузки регистров/записи и др.

Блок переименования регистров убирает ложные взаимозависимости между МОР, обеспечивая возможности их внеочередного выполнения. Этот блок за такт выбирает до четырех МОР (включая объединенные) из очереди МОР. Исходные архитектурные регистры и регистры результата здесь переименовываются во внутренние микроархитектурные, распределяются ресурсы (например, буферы загрузки/записи), определяются нужные порты диспетчеризации МОР. Здесь же выполняются некоторые примитивные команды типа «нет операции», разные формы обнуления регистров и др. В этом блоке может распределяться до двух команд перехода за такт (против одной в Nehalem). Это, конечно, способствует росту производительности.

В EE в Sandy Bridge был внесен ряд доработок, приводящих к уменьшению вероятности простоя (stall), уменьшению числа конфликтов и задержек обратной записи и др. EE включает три исполнительных стека: целочисленный общего назначения; для векторных (single instruction, multiple data, SIMD) команд, как целочисленных, так и с плавающей запятой; для команд набора x87.
Планировщик направляет МОР в один из шести портов выдачи, и эти МОР выполняются в соответствующих EU. На стадии завершения результаты выполнения выбираются в соответствии с указанным в исходном коде порядком.

Трудно перечислить все нововведения Sandy Bridge, но стоит еще упомянуть поддержку двух важных для повышения производительности технологий: HyperThreading, позволяющей получить два логических процессора вместо каждого физического ядра, и TurboBoost, позволяющей автоматически повышать частоту ядер относительно номинальной, если это разрешают термические условия.

Межсоединение процессорных ядер в Sandy Bridge представляет собой двунаправленную кольцевую шину. К ней подсоединены системный агент, кэш L3 и интегрированное графическое устройство (в некоторых моделях процессора E3 оно может отсутствовать). Пропускная способность шины при тактовой частоте ядер в 3 ГГц равна 384 Гбайт/с. Кэш L3 имеет четыре «среза» — по числу ядер в процессоре; каждый срез включает собственный порт, способный передавать 32 байт за такт.

Системный агент содержит в себе арбитр доступа к кольцу, контроллер дисплея, контроллеры PCIe (x16+x4/2*x8 +x4/x8 +3*x4), контроллер шины DMI, через который подсоединяется южный мост, и контроллер памяти. Последний поддерживает два канала DDR3/1066, 1333 или 1600 шириной 8 байт каждый. Каждый канал осуществляет внеочередную обработку запросов, реализуемую собственным планировщиком, и буфер данных емкостью 32 строки кэша. B Xeon с микроархитектурой Nehalem каналов памяти было три; возможно, в поддерживающих мультипроцессирование Xeon/Sandy Bridge каналов также будет три.

Четырехъядерные Xeon E3 производятся по технологии 32 нм, содержат около 1 млрд транзисторов и имеют тепловыделение до 95 Вт (у старших моделей).

Расширение AVX

Главным новшеством в Sandy Bridge, возможно, следует признать архитектурное расширение системы команд AVX [ 2 ]. AVX вводит 256-разрядные векторы и SIMD-регистры cоответствующей длины; новый трехоперандный синтаксис с новым префиксом VEX (вероятно, от Vector Extensions) для кодирования команд и расширения FMA (fused multiply-add, то есть команды типа «умножить-и-сложить», «умножить-и-вычесть» и др.) повышенной точности в соответствии со стандартом IEEE754/2008.

256-разрядные регистры YMM0-YMM15 в своих нижних 128 разрядах «эквивалентны» регистрам XMM. Вместе с VEX вводится также большое число новых команд с функциональностью, совпадающей с имеющимися ранее, но кодируемых с помощью VEX. Кроме того, в AVX представлены новые команды с новой функциональностью: загрузки 256-разрядных векторных регистров и пересылки между ними, команды работы с отдельными битами, расширенная команда умножения MULX для «длинных» целых чисел и др.

Поддержки 256-разрядной FMA в Sandy Bridge пока нет, вероятно, она появится в следующем поколении Ivy Bridge с типоразмером 22 нм. Там же ожидается поддержка расширения AVX2, которое включает работу с 256-разрядными целочисленными данными. Одновременно с поддержкой FMA возрастет и количество получаемых за такт результатов с плавающей запятой.

Измерения производительности

Для приведенных тестов использовался однопроцессорный сервер на базе Xeon E3-1240 3,3 ГГц (тактовая частота была фиксирована, поэтому пиковая производительность с двойной точностью была равна 26,4 GFLOPS) с памятью DDR3 8 Гбайт с симметричным заселением обоих каналов памяти. Некоторые результаты были сопоставлены с [ 3 ] для двухпроцессорного сервера с четырехъядерными Xeon E5520 2,27 ГГц (c микроархитектурой Nehalem) и памятью DDR2-1066 емкостью 12 Гбайт, расселенной равномерно по шести каналам памяти. Измерения проводились в 64-разрядной среде OpenSuSE 11.4 с использованием, в частности, Intel Fortran XE Composer 2011 версии 12.1/6.233 и библиотеки математических программ MKL 10.3.

Тесты Linpack при размерности задачи n=100 (табл. 2) являются хорошей оценкой производительности с плавающей запятой — влияние памяти здесь отсутствует, поскольку задача хорошо локализуется в кэше. Для ключей компиляции -fast и -xAVX достигается производительность 4,7 GFLOPS, но если ограничиться применением кодов SSE4.2 (-xSSE4.2), то производительность будет 5,0 GFLOPS. Не всегда применение команд AVX дает более высокую производительность.

Архитектура для повышения производительности
Таблица 2. Производительность сервера на базе Xeon E3-1240 на некоторых последовательных тестах

Интересно сравнить эти данные с результатами для Nehalem (2,6 GFLOPS), пересчитав производительность на единицу тактовой частоты, — окажется, что производительность ядра Sandy Bridge по сравнению с Nehalem выросла на 36%.

Данные тестов Linpack при n=1000 представляют аналогичный интерес, но здесь результаты определяются производительностью работы оптимизированных модулей (dgetrf, dgetrs) библиотеки MKL. На одном ядре при этом достигается производительность 18,9 GFLOPS, сопоставимая с пиковой, а в расчете на единицу тактовой частоты по сравнению с Nehalem производительность возросла на 71%. Это неплохое доказательство эффективности расширения числа устройств с плавающей запятой в Sandy Bridge. Распараллеливание теста на два и четыре ядра (табл. 2) следует признать вполне удовлетворительным.

Производительность ядра E3-1240 при умножении больших матриц (с применением MKL-модуля dgemm, n=8000) в расчете на единицу тактовой частоты возросла почти вдвое и составляет 24,7 GFLOPS — около 94% от пикового значения.

Результаты стандартных для оценки пропускной способности памяти тестов stream особенно важны для чувствительных к этому показателю приложений (например, вычислительной гидродинамики). Для многоядерных процессоров всегда встает проблема распределения пропускной способности между ядрами, которые могут вступать в конфликт по доступу в память — эта ситуация была обнаружена и в E3-1240.

Компиляция с ключами -fast -openmp (-xSSE4.2 слабо влияет на результат по сравнению с -xAVX) уже и на одном ядре позволяет достигнуть пропускной способности до 17,7 Гбайт/с (табл. 3), что достаточно близко к пиковому значению — 21,3 Гбайт/с для двух каналов DDR3-1333. На двух ядрах пропускная способность возрастает до 18,8 Гбайт/с, а на четырех уже уменьшается. Если компилятор не может так оптимизировать, как компилятор Intel (например, gfortran версий до 4.6.0 без поддержки Sandy Bridge), то масштабирование с числом ядер может быть выше.

Архитектура для повышения производительности
Таблица 3. Производительность с распараллеливанием

Архитектура для повышения производительности
Таблица 4. Ускорение при расчетах по Gaussian-09

В качестве иллюстрации распараллеливания реальных приложений приведены данные по задачам молекулярного моделирования (табл. 4) в квантовой химии, в рамках пакета Gaussian-09 [ 4 ]. В расчетах использованы молекулы тринитротриаминобензола (из стандартного test178, методом CIS), валиномицина (test397, DFT) и фуллерена C60 (DFT c расчетом частот), все — без учета симметрии.

Данные табл. 4 говорят о хорошем распараллеливании всех этих задач. Для фуллерена даже без перетрансляции кодов Gaussian-09 (под E3) при выполнении на Sandy Bridge производительность ядра E3-1240 в расчете на единицу тактовой частоты выше, чем у Nehalem.

Читайте также: