Помощничек
Главная | Обратная связь


Археология
Архитектура
Астрономия
Аудит
Биология
Ботаника
Бухгалтерский учёт
Войное дело
Генетика
География
Геология
Дизайн
Искусство
История
Кино
Кулинария
Культура
Литература
Математика
Медицина
Металлургия
Мифология
Музыка
Психология
Религия
Спорт
Строительство
Техника
Транспорт
Туризм
Усадьба
Физика
Фотография
Химия
Экология
Электричество
Электроника
Энергетика

АЛУ для чисел с плавающей точкой



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

1. Находится разность порядков большего и меньшего числа.

2. Мантисса меньшего числа сдвигается вправо на число бит, равное разности, полученное на шаге 1.

После этого производятся обычные целочисленные операции с мантиссой (см. раздел "Целочисленное АЛУ"). Далее, после получения результата вычислений иногда производится коррекция мантиссы числа с плавающей точкой. Алгоритм коррекции следующий:

1. Убираются все незначащие нули в левой части мантисса. Для этого осуществляется сдвиг влево мантиссы на n разрядов (n -- число незначащих нулей слева.)

2. После этого число n вычитается из порядка.

Как правило, операцию коррекции вызывают принудительно, а не запускают автоматически.

При работе этого устройства необходимо, чтобы ему правильно передавался и порядок, и мантиссу числа. Именно поэтому в большинстве устройств для проведения операций с плавающей точкой все операнды и результаты, а также промежуточные числа хранились в единообразной форме. Обычно ею является формат вещественных чисел с расширенной точностью, длиной 80 бит (10 байт). Преобразованием чисел в этот формат и из этого формата в формат других вещественных и целых чисел осуществляется устройством управления сопроцессора.

АЛУ десятично-двоичных чисел.

Это арифметико-логическое устройство применяется в дешевых моделях микрокалькуляторов. АЛУ в этих приборах имеет более сложный характер. Во первых, оно состоит из нескольких блоков по четыре разряда. А во-вторых, автоматически осуществляется так называемая десятичная коррекция чисел. Например:

8+9=17=10+7 1000+1001=10001=1010+0111
9+9=18=10+8 1001+1001=10010=1010+1000
5+4=9=0+9 0101+0100=1001=0000+1001
8+7=15=10+5 1000+0111=1111=1010+0101

Как видим, происходит лишь небольшое усложнение АЛУ, а все остальные операции остаются теми же, что и в целочисленном АЛУ. Из-за усложнения двоично-десятичного арифметико-логических устройств, они работают гораздо медленнее, чем аналогичные целочисленные АЛУ и АЛУ с плавающей точкой. Однако при этом устройство управления процессором упрощается за счет отсутствия команд конверсии двоичных чисел в двоично-десятичные и обратно. Это важно, поскольку большинство устройств ввода-вывода в микрокалькуляторе (и не только в нем!) способно работать лишь с двоично-десятичными числами.

Конвейер и АЛУ.

С появлением технологии MMX и конвейерной обработки (смотри соответствующую главу в этой книге, приводимую ниже) представление об АЛУ как об устройстве с двумя входами и одним выходом (см. рисунок D.1.8.) стало не соответствовать действительности. В случае конвейерной обработки происходит "распараллеливание" вычислений на уровне команды, когда за один такт складываются два или более операнда, результаты параллельных вычислений объединяются и т.п. Поэтому современные арифметико-логические устройства процессоров с конвейерной обработкой правильно изобразить схемой на рисунке D.1.9. Применение данной схемы показывает, как осуществляется на одном процессоре несколько параллельных вычислений на уровне инструкций, а не на уровне потоков. (смотри определение потоков в книгах, посвященные операционным системам.) Конвейер -- большой шаг в развитии микропроцессоров, сделанный фирмой Intel.

Рис. D.1.8. Представление классического АЛУ как "черного ящика".

Рис. D.1.9. Представление АЛУ процессора с конвейером как "черного ящика".

Введение конвейера

Идея конвейера, давным-давно предложенная Генри Фордом, состоит в том, что производительность цепочки последовательных действий определяется не сложностью этой цепочки, а лишь длительностью самой сложной операции. Иными словами, совершенно неважно, сколько человек занимаются производством автомобиля и как долго длится его изготовление в целом, - важно то, что если каждый человек в цепочке тратит, скажем, на свою операцию одну минуту, то с конвейера будет сходить один автомобиль в минуту, ни больше и ни меньше; независимо от того, сколько операций нужно совершить с отдельным автомобилем и сколько заняла бы его сборка одним человеком. Применительно к процессорам принцип конвейера означает, что если мы сумеем разбить выполнение машинной инструкции на несколько этапов, то тактовая частота (а вернее, скорость, с которой процессор забирает данные на исполнение и выдает результаты) будет обратно пропорциональна времени выполнения самого медленного этапа. Если это время удастся сделать достаточно малым (а чем больше этапов на конвейере, тем они короче), то мы сумеем резко повысить тактовую частоту, а значит, и производительность процессора.

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

 Выборка инструкции (FETCH) из памяти. Из программы извлекается инструкция, которую нужно выполнить.

 Декодирование инструкции (DECODE). Процессор "соображает", что от него хотят, и переправляет запрос на нужное исполнительное устройство.

 Подготовка исходных данных для выполнения инструкции.

 Собственно выполнение инструкции (EXECUTE).

 Сохранение полученных результатов.

Конвейеризация потенциально применима к любой процессорной архитектуре, независимо от набора команд и положенных в ее основу принципов. Даже самый первый x86-процессор, Intel 8086, уже содержал своеобразный примитивный "двухстадийный конвейер" - выборка новых инструкций (FETCH) и их исполнение осуществлялись в нем независимо друг от друга. Однако реализовать что-то более сложное для CISC-процессоров оказалось трудно: декодирование неоднородных CISC-инструкций и их очень сильно различающаяся сложность привели к тому, что конвейер получается чересчур замысловатым, катастрофически усложняя процессор. Подобных трудностей у RISC-архитектуры гораздо меньше (а SPARC и MIPS, например, и вовсе были специально оптимизированы для конвейеризации), так что конвейеризированные RISC-процессоры появились на рынке много раньше, чем аналогичные x86.

Недостатки конвейера неочевидны, но, как обычно и бывает, из-за нескольких "мелочей" реализовать грамотно организованный конвейер совсем не просто. Основных проблем три.

 Необходимость наличия блокировок конвейера. Дело в том, что время исполнения большинства инструкций может очень сильно варьироваться. Скажем, умножение (и тем более деление) чисел требуют (на стадии EXECUTE) нескольких тактов, а сложение или побитовые операции - одного такта; а для операций Load и Store, которые могут обращаться к разным уровням кэш-памяти или к оперативной памяти, это время вообще не определено (и может достигать сотен тактов). Соответственно, должен быть какой-то механизм, который бы "притормаживал" выборку и декодирование новых инструкций до тех пор, пока не будут завершены старые. Методов решения этой проблемы много, но их развитие приводит к одному - в процессорах прямо перед исполнительными устройствами появляются специальные блоки-диспетчеры (dispatcher), которые накапливают подготовленные к исполнению инструкции, отслеживают выполнение ранее запущенных инструкций и по мере освобождения исполнительных устройств отправляют на них новые инструкции. Даже если исполнение займет много тактов - внутренняя очередь диспетчера позволит в большинстве случаев не останавливать подготавливающий все новые и новые инструкции конвейер[Новые инструкции тоже не каждый такт удается декодировать, так что возможна и обратная ситуация: новых инструкций за такт не появилось, и диспетчер отправляет инструкции на выполнение "из старых запасов"]. Так в процессоре возникает разделение на две независимо работающие подсистемы: Front-end (блоки, занимающиеся декодированием инструкций и их подготовкой к исполнению) и Back-end (блоки, собственно исполняющие инструкции).

 Необходимость наличия системы сброса процессора. Поскольку операции FETCH и EXECUTE всегда выделены в отдельные стадии конвейера, то в тех случаях, когда в программном коде происходит разветвление (условный переход), зачастую оказывается, что по какой из веток пойти - пока неизвестно: инструкция, вычисляющая код условия, еще не выполнена[Вот здесь-то и нужны те самые режимы выставления флагов PowerPC, о которых шла речь в сноске 2]. В результате процессор вынужден либо приостанавливать выборку новых инструкций до тех пор, пока не будет вычислен код условия (а это может занять очень много времени и в типичном цикле страшно затормозит процессор), либо, руководствуясь соображениями блока предсказания переходов, "угадывать", какой из переходов скорее всего окажется правильным.

 Наконец, конвейер обычно требует наличия специального планировщика (scheduler), призванного решать конфликты по данным. Если в программе идет зависимая цепочка инструкций (когда инструкция-2, следующая за инструкцией-1, использует для своих вычислений данные, только что вычисленные инструкцией-1), а время исполнения одной инструкции (от момента запуска на стадию EXECUTE и до записи полученных результатов в регистры) превосходит один такт, то мы вынуждены придержать выполнение очередной инструкции до тех пор, пока не будет полностью выполнена ее предшественница. К примеру, если мы вычисляем выражение вида A•B+C с сохранением результата в переменной X (XfA•B+C), то процессор, выполняя соответствующую выражению цепочку из двух команд типа R4fR1•R2; R0fR3+R4, должен вначале дождаться, пока первая инструкция сохранит результат умножения A•B, и только потом прибавлять к полученному результату число С. Цепочки зависимых инструкций в программах - скорее правило, нежели исключение, а исполнение команды с записью результата в регистры за один такт - наоборот, скорее исключение, нежели правило, поэтому в той или иной степени с проблемой зависимости по данным любая конвейерная архитектура обязательно сталкивается. Оттого-то в конвейере и появляются сложные декодеры, заранее выявляющие эти зависимости, и планировщики, которые запускают инструкции на исполнение, выдерживая паузу между запуском главной инструкции и зависимой от нее.

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

В 1991–92 годах корпорация Intel, освоив производство сложнейших кристаллов с более чем миллионом транзисторов, выпустила i486 - классический CISC-процессор архитектуры x86, но с пятистадийным конвейером. Чтобы вы смогли оценить этот рывок, приведу две цифры: тактовую частоту по сравнению с i386 введение конвейера позволило увеличить втрое, а производительность на единицу частоты - вдвое[В i386 многие инструкции выполнялись за несколько тактов; а в i486 среднее "время" исполнения инструкции в тактах удалось снизить почти вдвое]. Правда, расплатой за это стала чудовищная сложность ядра i486; но такие "мелочи" по меркам индустрии центральных процессоров - пустяк: быстро растущие технологические возможности кремниевой технологии уже через пару лет позволили освоить производство i486 всем желающим. Но к тому моменту RISC-архитектуры сделали еще один шаг вперед - к суперскалярным процессорам

 




Поиск по сайту:

©2015-2020 studopedya.ru Все права принадлежат авторам размещенных материалов.