Большое число специализированных функциональных (исполнительных) устройств

Глава 31. Особенности структуры высокопроизводительных ядер процессоров для персональных компьютеров

Основные особенности структуры ядер процессоров

Основные особенности структуры ядер процессоров следующие:

Большая длина конвейера – до 12-16 ступеней.

Выполнение команд по предположению - «спекулятивное» выполнение.

Иерархическая структура подсистемы кэш-памяти.

Большое число специализированных функциональных (исполнительных) устройств.

Буферирование на всех этапах конвейера.

Суперскалярная организация.Этоозначает, что на каждом этапе обрабатываются сразу несколько потоков команд (операций) параллельно — от выборки из кэш-памяти команд до полного завершения («отставки»). Суперскалярность наряду с частотой является важнейшим показателем пропускной способности ядра процессора. Уровень суперскалярности (количество команд подготавливаемых к выполнению в одном такте) в современных высокопроизводительных ядрах процессоров варьируется от 3 до 4-5.

Предварительное преобразование архитектурных команд в промежуточные операции (микрооперации), более удобные для обработки и выполнения. Иногда такие операции называют RISC-подобными, исходя из того, что архитектуры RISC разрабатывались как раз для того, чтобы обеспечить простоту, удобство и эффективность обработки архитектурных команд. Преобразование команд является необходимым для архитектуры IA-32/64 с её крайне нерегулярной и запутанной системой команд. Однако и для достаточно регулярной RISC-архитектуры такое преобразование также производится — оно необходимо для разбиения некоторых сложных команд на простые операции. В англоязычной литературе эти микрооперации называют «МОПами» (либо просто «операциями»).

Внеочередное выполнение команд.Этоозначает, что команды не обязаны выполняться в функциональных устройствах строго в том порядке, который определён в программе. Более поздние команды могут выполняться перед более ранними командами, если не зависят от порождаемых ими результатов. Ядро процессора должно лишь гарантировать, что результаты «внеочередного» выполнения команд совпадают с результатами «правильного» последовательного их выполнения. Механизм внеочередного выполнения позволяет в значительной степени сгладить эффект от ожидания считывания данных из кэш-памятей верхних уровней и из оперативной памяти. Ожидание данных может длиться десятки и сотни тактов. Также он позволяет оптимизировать выполнение смежных операций, особенно при наличии сложных зависимостей между ними в условиях длительных задержек выполнения в устройствах и недостаточного количества регистров.

Поскольку исходная программа подразумевает последовательную модель выполнения, машинные команды должны считываться также последовательно. Кроме того, есть такое понятие, как «отставка» команды, которое подразумевает, что данная команда выполнена вместе со всеми командами, которые ей предшествовали в тексте программы. Таким образом, команды уходят в «отставку» строго последовательно, именно в том порядке, который задаётся программой.

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

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

если предсказанный участок программы уже продешифрирован и находится в кэш-памяти продешифрированных команд (L0m – в терминологии фирмы Intel), то он читается из него и попадает в буфера подсистемы обработки данных;

если предсказанный участок программы находится в кэш-памяти команд первого уровня (L1К), то читается порция командной информации, дешифрируется сначала предварительным дешифратором (предекодером), а затем несколькими (в зависимости от степени суперскалярности) окончательными дешифраторами и попадает в буфера подсистемы обработки данных;

если предсказанный участок программы отсутствует в кэш-памятях всех уровней, то:

требуемая командная информация загружается из оперативной памяти во все уровни кэш-памяти (в том числе и в кэш-память L1K);

читается из кэш-памяти L1K порция командной информации, дешифрируется сначала предекодером, а затем несколькими (в зависимости от степени суперскалярности) окончательными дешифраторами и попадает в буфера подсистемы обработки данных.

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

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

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