Новые команды процессора Pentium III
Содержание:
1. Введение в архитектуру INTEL
1.1. Краткая история архитектуры INTEL
1.2. Увеличение производительности архитектуры INTEL и закон Мура
1.3. Краткая история блока с плавающей запятой архитектуры INTEL
1.4. Введение в микроархитектуру процессоров семейства P6
1.5. Детальное описание микроархитектуры семейства процессоров P6
1.5.1. Подсистема памяти
1.5.2. Блок выборки/декодирования
1.5.3. Накопитель команд (буфер переупорядочивания)
1.5.4. Блок диспетчерезации/выполнения
1.5.5. Блок сброса
2. Программирование с помощью STREAMING SIMD EXTENSIONS (SSE)
2.1. Общее представление о SSE
2.1.1. SIMD-регистры с плавающей точкой
2.1.2. Тип данных SIMD с плавающей точкой.
2.1.3. Модель выполнения SIMD
2.1.4. Формат данных в памяти
2.1.5. Формат данных SIMD регистра с плавающей точкой
2.1.6. SIMD регистр состояния и управления
2.1.7. Поле управления округлением
2.1.8. Режим Flush To Zero
2.2. Команды Потокового Расширения SIMD
2.2.1. Операнды команд
2.3. Обзор SIMD-команд
2.3.1. Команды копирования данных
2.3.2. Арифметические команды
2.3.2.1. Команды упакованного/скалярного сложения и вычитания
2.3.2.2. Команды упакованного/скалярного умножения и деления
2.3.2.3. Команды упакованого/скалярного вычисления квадратных корней
2.3.2.4. Команды упакованого/скалярного нахождения максимума и минимума
2.3.3. Команды сравнения
2.3.4. Команды преобразования типов данных
2.3.5. Логические команды
2.3.6. Дополнительные команды SIMD над целыми
2.3.7. Команды перестановки
2.3.8. Команды управления состоянием
2.3.9. Команды управления кэшированием
2.3.9.1 Некэширующие команды записи в память
2.3.9.2 Упреждающее кэширование
2.3.9.3 Принудительная запись
3. Примеры программирования с помощью SSE
3.1. Проверка наличия процессорной поддержки
3.2. Скалярное произведение векторов
3.3. Умножение матрицы на вектор
3.4. Приближенное нахождение обратных значений
3.5. Устранение ветвлений
3.6. Преобразование из FP в целое
3.7. Упреждающее кэширование
4. Литература.
1. Введение в архитектуру INTEL
1.1. Краткая история архитектуры INTEL
Развитие архитектуры Intel (IA) может быть прослежено от микропроцессоров 8085 и 8080 до микропроцессора 4004 (первого микропроцессора, созданного Intel в 1969). Однако, первым настоящим процессором в семействе IA является 8086, и выпущенный вслед за ним более дешевый процессор 8088. Объектный код программ созданных для этих процессоров может быть запущен и на более поздних версиях процессора семейства IA.
Процессор 8086 имеет 16-разрядные регистры и 16-разрядную внешнюю шину данных, с 20-разрядной адресацией которая позволяет адресовать 1-Mbyte адресного пространства. Процессор 8088 такой же за исключением меньшей внешней шины данных - 8 бит. В эти процессоры вводится сегментация, но только в “Реальном Режиме”; 16-разрядные регистры могут действовать как указатели на адрес в сегментах размером до 64 KBytes. Четыре сегментных регистра содержат 20-разрядный базовый адрес текущего активного сегмента; значит без переключения между сегментами можно адресовать до 256 KBytes.
В процессоре Intel 80286 вводится Защищенный Режим. Этот новый режим использует содержимое сегментных регистров как селектор или указатель в таблице дескриптора. Дескриптор хранит 24-битный базовый адрес, позволяющий адресовать до 16 Mbyte физической памяти, поддерживает виртуальное управление памятью и различные механизмы защиты. Это включает проверку границы сегмента, опции сегментов только для чтения и только для запуска, и четыре уровня привилегей для защиты кода операционной системы (в некоторых подразделах, если требуется) от приложений или программ пользователя. Более того, переключение задач и локальная таблица дескриптора позволяет операционной системе защитить приложения или программы пользователя друг от друга.
В процессоре Intel386 вводятся в архитектуру 32-разрядные регистры, для использования в вычислениях и адресации памяти. Нижняя половина каждого 32-разрядного регистра имеет значение одного 16-разрядного регистра предыдущих двух поколений, для обеспечения полной обратной совместимости. Был введен новый Виртуальный Режим 8086 для повышения быстродействия на новой 32-разрядной машине программ созданных для процессоров 8086 и 8088. 32-разрядная адресация поддерживается внешней 32-битной шиной адреса, что позволяет адресовать 4-GByte адресного пространства, и также позволяет чтоб размер каждого сегмента был до 4-GByte. Первоночальные инструкции были расширены новыми инструкциями с 32-разрядными операндами и формой адресации. В процессоре Intel386 также вводится страничная организация памяти, с фиксированным размером страницы 4-Kbyte, она предусматривает метод для управления виртуальной памятью который значительно лучше использования сегментов (это было намного эффективнее для операционных систем, и полностью прозрачно для приложений без значительной потери в скорости). Кроме того, возможность определения сегментов размером в 4-GBytes физического адресного пространства, вместе с страничной организацией памяти, позволяет создавать защищенную “плоскую модель” адресной системы, включая полную поддержку широко используемых на mainframe операционной системы UNIX.
В архитектуре процессоров Intel поддерживается обратная совместимость с объектным кодом для сбережения инвестиций в программное обеспечение, но в тоже время, в каждом новом поколении используются все более эффективные микропроцессорные архитектуры и технологии конструирования. Intel работала по внедрению и соединению сложной техники архитектуры mainframe в микропроцессорную архитектуру. Многие модели паралельной обработки намного усиливали производительность техники, и процессор Intel386 был первым процессором IA в который включили шесть паралельных стадий. Это Интерфейсный Блок Шины (доступ к памяти и устройству ввода/вывода других блоков), Блок Предварительного Кода (получает объектный код из Блока Шины и помещает его в 16-байтную очередь), Блок Декодирования Инструкции (декодирует объектный код из Предварительного блока в микрокод), Блок Выполнения (выполняет инструкции микрокода), Сегментный Блок (переводит логические адреса в линейные адреса и выполняет проверку защиты), и Страничный Блок (переводит линейные адреса в физические, выполняет проверку страничной защиты, и содержит кэш с информацией о 32 наиболее часто используемых страницах).
В процессор Intel486 добавлена возможность параллельного выполнения, с помощью расширения Блока Декодирования Инструкции и Блока Выполнения процессора Intel386 в пять конвейерных стадий, где каждая стадия (если нужно) работает параллельно с другими и одновременно может выполняться до пяти инструкций в разных стадиях. Каждая стадия может выполнить свою работу над одной инструкцией за один такт, то есть процессор Intel486 может выполнить работу над одной инструкцией за один такт CPU. Также к процессору Intel486 был добавлен 8-Kbyte чип кэша L1 для увеличения процента инструкций которые могут быть выполнены за один такт: инструкции доступа в память (если операнд находился в кэше L1). В процессоре Intel486 впервые на чип с CPU был интегрирован Блок арифметического устройства с плавающей запятой (FPU) и добавлены новые контакты, биты, и инструкции для поддержки более сложных и мощных систем (поддержку L2 кэша и мультипроцессорности).
Позже в поколение процессоров Intel486, Intel добавила в процессор Intel486 SL Enhanced (расширенный) функции поддержки энергосбережения и другие возможности системного управления. Эти функции были развиты в процессорах Intel386 SL и Intel486 SL, которые были специализированы для быстро растущего рынка ноутбуков PC работающих от батарей. Эти функции включали новый Режим Управления Системой, запускаемый собственным выделенным контактом прерывания, который позволяет управлять системой (такой как управление энергосбережением) и добавляется к системе прозрачно для других операционных систем и всех приложений. Функции Стоп Таймер и Автоматическая Остановка позволяют CPU работать на пониженной частоте (для сохранения энергии), или остановиться (с сохранением текущего состояния).
В процессор Intel Pentium для достижения суперскалярной производительности была доблавлена вторая линия конвейерной обработки (две линии конвейера, известных как u и v, вместе могут выполнять две инструкции за один такт). Также был удвоен кэш L1, 8-Kbyte для кода, и другие 8-Kbyte для данных. Кэш данных для обеспечения более эффективного режима обратной записи использует протокол MESI. Для увеличения производительности в конструкциях циклов было добавлено прогнозирование ветвлений с чипом таблицы переходов. Основные регистры остались 32 битные, но добавилась внутренняя шина данных 128 и 256 бит, для увеличения скорости внутренней передачи данных, и внешняя шина данных была увеличена до 64 бит. Был добавлен Дополнительный Программируемый Контролер Прерываний (Advanced Programmable Interrupt Controller) для поддержки систем с несколькими процессорами Pentium, и для поддержки двух процессорных систем были разработаны новые контакты и специальный режим (dual processing) .
В процессор Intel Pentium Pro добавлено “Динамическое Выполнение”. Он имеет трехходовую суперскалярную архитектуру, это значит что процессор может выполнять три инструкции за каждый такт CPU. Это осуществляется внедрением большего параллелизма чем в процессоре Pentium. В суперскалярной реализации процессора Pentium Pro предусматривается Динамическое Выполнение (анализ потоков микро-данных, нестандартное выполнение, улучшенное прогнозирование ветвлений, и прогностическое выполнение). Три устройства декодирования инструкций работают параллельно декодируя объектный код в более малые операции называемые “микрокодом” (“micro-ops”). Они попадают в накопитель инструкций, и (когда нет взаимосвязи) могут быть выполнены пятью параллельными блоками выполнения (два целых, два FPU и один блок для работы с памятью). Блок Сброса изъемает выполненый микрокод в порядке настоящего расположения в программе, учитывая все ветвления. Мощность процессора Pentium Pro дополнительно расширена его кэшом: он имеет такие же два 8-KByte чипа кэша L1 как и у процессора Pentium, и к тому же у него есть 256-KByte кэш L2 который находится в том же корпусе что и CPU, использует выделенную 64-разрядную шину. Кэш L1 - двухпортовый, кэш L2 поддерживает до 4 паралельных обращений, и 64-разрядная внешняя шина данных ориентированна по направлению входных данных, это значит что каждое обращение описывается отдельным запросом и ответом, с многочисленными запросами пока ожидается ответ. Эти функции паралелизма для доступа к данным работают с возможностью параллельного выполнения для обеспечения “non-blocking” архитектуры в которой процессор намного полнее используется. Также в процессоре Pentium Pro шина адреса увеличена до 36-бит, что позволяет адресовать до 64 Gbytes физического адресного пространства.
В процессор Pentium II к архитектуре процессора Pentium Pro добавлены команды MMX. Для процессора Pentium II вводится новая спецификация установки в материнскую плату слот 1 и слот 2. В этой новой спецификации кэш L2 выносится из кристала. Для слот 1 и слот 2 используются ножевое соединение вместо сокет. В процессоре Pentium II увеличен кэш данных L1 и кэш инструкций L1 до 16 KByte каждый. В процессоре Pentium II размер кэша L2 может быть 256 KBytes, 512 KBytes и 1 MByte или 2 MByte (только для слот 2). Процессоры слота 1 используют “половинную тактовую частоту” шины, а процессоры слота 2 используют “полную тактовую частоту ” шины.
Процессор Pentium III базируется на архитектуре процессоров Pentium Pro и Pentium II. В процессоре Pentium III введены 70 новых инструкций. Эти инструкции исполняются на существующих функциональных блоках архитектуры.
1.2. Увеличение производительности архитектуры INTEL и закон Мура
В середине 1960 годов, Председатель Intel Gordon Moore вывел принцип или закон который остается верным уже больше трех десятилетий: мощность вычислений и сложность (или приблизительно, количество транзисторов в каждом чипе CPU) кремниевой интегрированной микросхемы процессора удваивается каждые два года, и стоимость каждого чипа CPU уменьшается вдвое.
Процес-сор Intel |
Дата выпуска продук-ции |
Произво-дитель-ность в MIPs |
Макси-мальная частота процессора в момент выпуска |
Количество транзи-сторов на кристале |
Размер регист-ров CPU |
Размер внеш-ней шины данных |
Макси-мальный размер внешней памяти |
Кэш в CPU |
8086 |
1978 |
0.8 |
8 MHz |
29 K |
16 |
16 |
1 MB |
None |
Intel 286 |
1982 |
2.7 |
12.5 MHz |
134 K |
16 |
16 |
16 MB |
None |
Intel 386 DX |
1985 |
6.0 |
20 MHz |
275 K |
32 |
32 |
4 GB |
None |
Intel 486 DX |
1989 |
20 |
25 MHz |
1.2 M |
32 |
32 |
4 GB |
8 KB L1 |
Pentium |
1993 |
100 |
60 MHz |
3.1 M |
32 |
64 |
4 GB |
16KB L1 |
Pentium Pro |
1995 |
440 |
200 MHz |
5.5 M |
32 |
64 |
64 GB |
16KB L1 256 KB или 512 KB L2 |
Pentium II |
1997 |
466 |
266 MHz |
7 M |
32 |
64 |
64 GB |
32KB L1 256 KB или 512 KB L2 |
Pentium III |
1999 |
1000 |
500 MHz |
8.2 M |
32 GP 128 SIMD-FP |
64 |
64 GB |
32KB L1 512 KB L2 |
Таблица 1-1. Производительность процессоров и другие особенности архитектуры
1.3. Краткая история блока с плавающей запятой архитектуры INTEL
Недостатком блока с плавающей точкой (Floating-Point Unit (FPU)) до процессора Intel486 было то что он не был интегрирован в процессор (CPU), но начиная с первых поколений процессоров были предусмотренны возможности для усовершенствования производительности блока с плавающей точкой. (Так как первые FPU были на отдельных микросхемах, они часто обращались к математическому расширению процессора (numeric processor extension (NPX)) и математическому сопроцессору (math coprocessor (MCP)).) С каждым новым поколением, Intel делала значительное увеличение мощности и гибкости FPU, и даже сохранила полную обратную совместимость. В Процессоре Pentium Pro осуществляется совместимость с объектным кодом для процессоров 8087, Intel 287, Intel 387 DX, Intel 387 SX, и математического сопроцессора Intel 487 DX, Intel486 DX и Pentium.
Математическое расширение процессора 8087 (NPX) было разработано для использования в системах семейства 8086. 8086 стал первым микропроцессором этого семейства, где для обеспечения высокой производительности математических функций разделялся блок обработки. В NPX 8087 для процессоров этого семейства встроены полные математические условия обработки в соответствие с требованиями ранего стандарта IEEE 754 для двоичной арифметики с плавающей точкой.
Начиная с сопроцессора Intel 287, блок математических вычислений был расширен для поддержки высокопроизводительной многозадачной и многопользовательской системы 80286. Многократое использование задачами математического расширения процессора было возможно благодаря полной защиты управления памятью 80286 и его защитными возможностями.
Математические сопроцессоры Intel 387 DX и SX это третее поколение сопроцессоров Intel. В них реализованна окончательная версия стандарта IEEE 754, добавлены новые тригонометрические команды, и использование новой конструкции и технологического процесса CHMOS-III позволяет увеличить тактовую частоту (тоесть требуется меньше тактов для выполнения одной команды).
FPU процессора Intel486 это расположенный на кристале процессора эквивалент математического сопроцессора Intel 387 DX согласующийся с обеими стандартами IEEE 754 и более современным, обобщенным стандартом IEEE 854. Так как FPU расположен на кристале увеличивается производительность математических операций.
В процессоре Pentium FPU был полностью переконструирован FPU процессора Intel486, он поддерживает оба стандарта IEEE 754 и 854. Для общих команд включая ADD, MUL и LOAD были разработаны более быстрые алгоритмы которые обеспечивают увеличение в скорости как минимум в три раза по сравнению с FPU процессора Intel486. Большинство приложений могут достигнуть пяти-кратного увеличения в скорости по сравнению с FPU процессора Intel486 или даже большей производительности при конвейерной обработке.
1.4. Введение в микроархитектуру процессоров семейства P6
Процессоры семейства P6 (представленые в 1995 году фирмой Intel) представляют собой ранюю реализацию наиболее современных процессоров в семействе IA. Как и их предшественники, процессор Pentium (представлен в 1993 году фирмой Intel), процессор Pentium Pro, с его суперскалярной архитектурой, устанавливают впечатляющие стандарты производительности. В проектирование процессоров семейства P6, одной из главных задач было значительное увеличение производительности процессоров Pentium в то время как используется старый процес производства BICMOS (тоесть 0.6-микрометр, четыре слоя, метал), тоесть это значит что производительность может быть повышена только благодоря улучшеннию архитектуры.
Рисунок 1-1. Блок обработки и его связь с подсистемой памяти
Микроархитектура процессоров семейства P6 это трехходовая суперскалярная, конвейерная архитектура. Термин “трехходовая суперскалярная” (three-way superscalar) значит что используя технику паралельной обработки, процессор может в среднем за один такт декодировать (decode), деспетчеризировать (dispatch), и выполнить (execution) три команды. Для обеспечения такого уровня пропускной способности, в семействе процессоров P6 используется расщепление суперконвейера на l2-стадии (12-stage) которые поддерживают нестандартное выполнение команд. На Рисунке 1-1 показан концептуальный вид конвейера, с разделением ковейера на четыре блока обработки (блок выборки/декодирования (fetch/decode unit), блок диспетчерезации/выполнения (dispatch/execute unit), блок сброса (пересылка результатов в архитектурные регистры и память в ожидании разрешения всех взаимозависимостей исполненных команд) (retire unit), и накопитель команд(instruction pool)). Команды и данные поступают к этим блокам по шине интерфейса.
Для постоянного поступления команд и данных в конвейер выполнения команд, микроархитектура семейства процессоров P6 включает два уровня кэша. Кэш L1 состоит из 8-KByte кэша команд и 8-KByte кэша данных, они вплотную присоединенны к конвейеру. Кэш L2 может быть 256-KByte, 512-KByte, или 1-MByte статической RAM которая присоединена к ядру процессора через 64-битную шину кэша.
Центральная часть микроархитектуры семейства процессоров P6 это введение механизма нестандартного выполнения (out-of-order execution mechanism) также называемого “динамическим выполнением” (“dynamic execution”). Динамическое выполнение включает три концепции обработки информации:
Глубокое прогнозирование ветвлений (Deep branch prediction).
Динамический анализ потока данных (Dynamic data flow analysis).
Прогностическое выполнение (Speculative execution).
Прогнозирование ветвлений это концепция на которой базируются большинство mainframe и быстродействующие микропроцессорные архитектуры. Эта концепция позоляет процессору декодировать команды вне ветвлений для полного использование ковейера команд. В семействе процессоров P6, блок выборки/декодирования команд использут сильно оптимизированный алгоритм прогнозирования ветвлений для предсказания направления потока команд в многоуровневом ветвление, вызовах процедур и возвратов из них.
Динамический анализ потока данных включает в себя анализ потока данных проходящих через процессор в реальном времени для определения зависимостей данных и регистров и для обнаружения возможностей использования нестандартного выполнения команд. В семействе процесоров P6 блок диспетчерезации/выполнения команд может одновременно следить за многими командами и выполнять их в порядке который оптимизирует использование процесорного блока множественного выполнения, до тех пор пока сохраняется целостность данных. Такое нестандартное выполнение держит занятым блок выполнения команд даже когда происходит кэш промах (cache miss) и при зависимости данных в командах.
Прогностическое выполнение это возможность процессора выполнять команды впереди счетчика команд, но в конце концов фиксировать результат в порядке поступления команд. Для обеспечения возможности прогностического выполнения, в микроархитектуре семейства процессоров P6 разделяется диспетчерезация и выполнение команд. Процессорные блоки диспетчерезации/выполнения используют анализ потока данных для выполнения всех доступных команд в накопителе команд и сохраняет результат в временные регистры. Блок сброса линейно ищет в накопителе команд выполненые команды в которых нет зависимостей данных с другими командами или неразрешенных ветвлений. Когда завершенные команды найдены, блок сброса фиксирует результаты этих команд в памяти и/или в регистрах IA (восемь регистров общего назначения и восемь регистров с плавающей точкой) в порядке их поступления и удаляет эти команды из накопителя команд.
Вследствие глубокого прогнозирование ветвлений, динамического анализа потока данных и прогностического выполнения, динамическое выполнение устраняет ограничение линейного выполнения последовательности команд в традиционных фазах выборки и выполнения команд. Это позволяет чтоб команды декодировались глубоко в мультиуровневых ветвлениях для полного использование ковейера команд. Это также помогает нестандартному выполнению команд держать процессорный блок выполнения команд запущенным на полную его вместимость. И наконец, это помогает подерживать целостность данных и связность программы при возращение результатов выполненых функций (в порядке их поступления).
1.5. Детальное описание микроархитектуры семейства процессоров P6
На Рисунке 1-2 показана функциональная блок-схема микроархитектуры семейства процессоров P6. На этой диаграме, следующие блоки состоят из четырех блоков обработки и подсистемы памяти показаных на Рисунке 1-1:
Подсистема памяти – Системная шина, кэш L2, блок интерфейса шины, кэш команд (L1), кэш данных (L1), блок интерфейса памяти и буфер переупорядочивания памяти (memory reorder buffer).
Блок выборки/декодирования – Блок выборки команд, буфер возможных переходов (branch target buffer), декодер команд, последовательность микрокода (microcode sequencer) и таблица псевдонимов регистров (register alias table).
Накопитель команд – буфер переупорядочивания (Reorder buffer).
Блок диспетчерезации/выполнения – буфер резервации (Reservation station), два целых блока, один x87 блок с плавающей точкой, два блока генерации адреса, и два SIMD блока с плавающей точкой.
Блок сброса – Блок сброса и регистровый файл сброса (retirement register file).
Рисунок 1-2. Функциональная блок-схема микроархитектуры семейства процессоров P6
1.5.1. Подсистема памяти
Подсистема памяти для семейства процессоров P6 состоит из главной системы памяти, первичного кэша (L1) и вторичного кэша (L2). Блок интерфейса шины обращается к системе памяти через внешнюю системную шину. Эта 64-битная шина является шиной работающей на основание транзакций (transaction-oriented bus), это значит что каждая операция доступа к шине обрабатывается как отдельный запрос и ответ. Пока блок шины интерфейса ожидает ответ от запроса к шине, он может выполнить многожество дополнительных запросов.
Блок шины интерфейса обращается к близко расположенному кэшу L2 через 64-битную шину кэша. Эта шина также является работающей на основание транзакций, и поддерживает до четырех параллельных обращений к кэшу и работает на полной частоте процессора.
Доступ к кэшу L1 осуществляется через внутрение шины, также на полной частоте. 8-KByte кэш команд L1 это четырех-направленый ассоциативный набор (four-way set associative); 8-KByte кэш данных L1 это двухпортовый и двух-направленый ассоциативный набор, поддерживает одну операцию чтения и одну операцию записи.
Связь между кэшом и системной памятью поддерживается с использованием кэш протокола MESI (модифицированный, исключающий, совместный, недействительный (modified, exclusive, shared, invalid)). Этот протокол благоприятствует кэш связи в одно- и мульти-процессорных системах. Он также может обнаружить проблемы связи созданные самомодифицируемым кодом.
Запросы к памяти из процессорного блока выполнения проходят через блок интерфейса памяти и буфер переупорядочивания памяти. Этот блок был создан для поддержки запроса плавного потока обращения к памяти через иерархию кэша и системной памяти для предотвращения блокирования доступа к памяти. Кэш данных L1 автоматически передает кэш промах в кэш L2, и затем, если нужно, блок интерфейса шины передает кэш промах L2 в системную память.
Запросы к памяти к кэшу L2 или системной памяти проходят через буфер переупорядочивания памяти, который функционирует как устройство распределения и диспетчерезации. Этот блок отслеживает все запросы к памяти и он может переупорядочивать некоторые запросы для предотвращения блокирования и улучшение пропускной способности. Например, буфер переупорядочивания памяти позволяет чтоб операция загрузки передавалась раньше операции записи.
1.5.2. Блок выборки/декодирования
Блок выборки/декодирования читает поток команд из кэша команд L1 и декодирует их в серию микрокода (“micro-ops”). Этот поток микрокода (остается в порядке поступления команд) посылается в накопитель команд.
Блок выборки команд выбирает одну 32-байтную кэш линию из кэша команд. Он отмечает начало и конец команд в кэш линии и передает 16 выровненых байт в декодер.
Блок выборки команд вычисляет командный указатель, базируемый на входных данных буфера возможных переходов, статуса исключения/прерывания и индикатора промаха в прогнозирование перехода из блока целого выполнения. Наиболее важная часть этого процеса это предсказание переходов выполняемая буфером возможных переходов. Используя расширенный алгоритм Йеха (Yeh algorithm), буфер возможных переходов на 512 адресов просматривает намного команд вперед от значения счетчика команд в момент изъятия. Внутри этого набора команд может быть несколько ветвлений, вызовов процедур и возвратов из них, и все они должны быть правильно предсказаны.
Декодер команд содержит три параллельных декодера: два декодера простых команд и один декодер сложных команд. Каждый декодер преобразовует команду в одну или несколько трехместных микро-операций (на каждый микрокод два логических источника и один логический результат). Микрокод это элементарная инструкция которая выполняется шестью процессорными блоками параллельного выполнения.
Многие команды преобразовываются декодером простых команд непосредственно в одну микро-операцию. Более сложные команды преобразовываются в последовательность предварительно запрограммированных микро-операций полученных из генератора микрокода. Декодер команд также обрабатывает командные префиксы и операции циклов. Декодер команд может генерировать до шести микро-операций за один такт (одну для каждого простого декодера и четыре для сложного декодера команд).
Набор регистров IA может вызывать прекращение работы из-за регистровой зависимости. Для решения этой проблемы, в процессор введены 40 внутренних регистров общего назначения, которые используются при вычислениях. Эти регистры могут содержать целые значения и значения с плавающей точкой. Для назначения внутренних регистров, поставленные в очередь микро-операции из декодера команд посылаются в таблицу псевдонимов регистров, где логические регистры IA преобразутся в внутренние ссылки на физические регистры.
На последнем шаге процесса декодирования, распределитель в таблице псевдонимов регистров добавляет бит статуса и флаги к микрокоду (готовит для нестандартного выполнения) и посылает результирующую микро-операцию в накопитель команд.
1.5.3. Накопитель команд (буфер переупорядочивания)
Поток микрокода до попадания в накопитель команд (известного также как буфер переупорядочивания) остается в том же порядке в каком команды поступали на декодер команд. Не выполнятся ни каких перестановок инструкций.
Буфер переупорядочивания это масив ассоциативной памяти, расположенный в 40 регистрах. Он содержит микрокод который должен быть выполнен и также тот что уже выполнен но еще не зафиксирован машинным статусом. Блок диспетчерезации/выполнения может выполнять команды из буфера переупорядочивания в любом порядке.
1.5.4. Блок диспетчерезации/выполнения
Блок диспетчерезации/выполнения это блок нестандартного (нелинейного) выполнения который распределяет и выполняет микро-операции хранящиеся в буфере переупорядочивания в зависимости от доступных ресурсов, зависимостей данных и временно сохраненых результатов прогностического выполнения.
Распределение и диспетчерезация микрокода в буфере переупорядочивания обрабатывается буфером резервации (буфер, содержащий команды, которые уже декодированы, но еще не выполнены). Он непрерывно сканирует буфер переупорядочивания в поисках микро-операций которые уже выполнены (то есть, доступны все операнды-источники) и отправляет их в доступный блок выполнения. Результат выполнения микро-операции возвращается в буфер переупорядочивания и сохраняется вместе с микро-операцией до тех пор, пока не будет удален. Этот процесс распределения и диспетчерезации поддерживает класическое нестандартное выполнение, тоесть микро-операция отправляется в блок выполнения по строго опеределенным ограничениям потока данных и доступна средствам выполнения, независящая от оригинального порядка команд. Когда одновременно доступны две или более микро-операции одного типа (например, операции над целыми) они выполняются буфером переупорядочивания в порядке FIFO (first-in, first-out ("первым пришел - первым обслужен")).
Выполнение микрокода осуществляется двумя блоками вычислений целых, двумя блоками вычислений с плавающей точкой и одним блоком интерфейса памяти, позволяя распределить до пяти микро-операций за один такт.
Два блока вычислений целых могут параллельно обрабатывать две микро-операции над целыми. Один из блоков вычислений целых предназначен для обработки микро-операций перехода. Этот блок может обнаруживать промахи в прогнозирование перехода и сигнализировать буферу переупорядочивания про перезапуск конвейера. Эта операция выполняет следующие действия: Декодер команд связывает каждую микро-операцию перехода с обоими адресами назначения перехода (прогнозированное назначение и назначение провала(fall-through destination)). Когда блок вычислений целых выполняет микро-операцию перехода, он может определить какое назначение (прогнозированное или провала) было взято. Если взята прогнозированная ветка, тогда прогностически выполненная микро-операция отмечается используемой и продолжается выполнение в соответствии с прогнозированным командным потоком. Если прогнозированная ветка не была взята, то блок выполнения перехода в блоке вычислений целых изменяет состояние всех микро-операций следующих за выполненной микро-операцией для удаления их из накопителя команд. Затем он устанавливает правильное назначение перехода в буфер возможных переходов, который перезапускает конвейер с новым адресом.
Блок интерфейса памяти обрабатывает микро-операции чтения и записи. Для выполнения операции чтения нужно только установить адрес памяти, это значит что она может быть закодированна одной микро-операцией. Для выполнения операции записи нужно установить адрес и данные для записи, это значит что она кодируется в две микро-операции. Часть блока интерфейса памяти которая обрабатывает операции записи имеет два порта позволяющих параллельно обрабатывать микро-операции адреса и данных. Таким образом, блок интерфейса памяти может выполнять за один такт операцию чтения и записи.
1.5.5. Блок сброса
Блок сброса фиксирует результат прогностического выполнения микрокода в постояное машинное состояние и удаляет микрокод из буфера переупорядочивания. Как и буфер резервации, блок сброса непрерывно проверяет состояние микрокода в буфере переупорядочивания, ища те операции которые были выполнены и у которых нет никаких зависимостей с другими микро-операциями в накопителе команд. Затем он “сбрасывает” завершенные микро-операции в их оригинальном порядке, принимая во внимание прерывания, исключения, точки прерывания (breakpoints) и промахи в прогнозирование перехода.
Блок сброса может “сбрасывать” три микро-операции за один такт. Во время сброса микро-операции, он записывает результат в регистровый файл сброса и/или память. Регистровый файл сброса (retirement register file) содержит регистры IA (восемь регистров общего назначения и восемь регистров для данных с плавающей точкой). После фиксирования результата в машинное состояние, микро-операция удаляется из буфера переупорядочивания.
2. Программирование с помощью STREAMING SIMD EXTENSIONS (SSE)
Потоковое Расширенние SIMD (Streaming SIMD Extensions (Single Instruction, Multiple Data - одна команда, несколько элементов данных)) это обобщающее название всех новых возможностей процессора Pentium III, что созданы для повышения производительности в мультимедиа и информационных приложениях. Эти нововведения (которые включают новые регистры, типы данных, и команды) объединяются с выполняемой моделью SIMD для повышения быстродействия приложений. Применение новых SIMD-команд значительно увеличивает производительность приложений, обрабатывающих данные с плавающей запятой, или приложений которые в основном используют алгоритмы с интенсивными вычислениями, выполняя повторяющие операции над большими масивами простых, отрицательных елементах данных. Также от SSE выигрывают приложения которым нужен постоянный доступ к большим размерам данных.
Новые SIMD-команды, реализованные в процессоре Pentium III, увеличивают производительность прикладных программ в следующих областях:
видео
комбинирование графики и видео
обработка изображений
звуковой синтез
распознавание, синтез и компресия речи
телефония
видео конференции
2D и 3D графика.
2.1. Общее представление о SSE
В SSE вводятся новые, общего назначения, команды, которые оперируют над новым набором регистров состоящий из восьми 128-разрядных SIMD-регистра с плавающей точкой. Эти команды позволяют программисту создавать алгоритмы, в которых можно смешивать упакованные данные одинарной точности с плавающей точкой и данные с целыми используя инструкции SSE и MMX соответственно. В дополнение к этим инструкциям SSE также обеспечивает инструкции для управления кэшированием всей MMX технологии и 32-битных типов данных. Эти инструкции включают возможность записи данных в память без “засорения” кэша, и возможность упреждающей выборки кода/данных до их использования.
Потоковое Расширение SIMD обеспечивает следующие новые возможности при программировании оборудования IA:
Восемь SIMD-регистров с плавающей точкой (XMM0 - XMM7).
Тип данных SIMD (упакованные числа одинарной точности с плавающей точкой) - 128-бит.
Набор команд SSE.
2.1.1. SIMD-регистры с плавающей точкой
В Потоковом Расширении SIMD содержится восемь 128-разрядных регистров общего назначения, каждый из них может быть напрямую адресован. Так как эти регистры новые, то для использования нуждаются в поддержке операционной системы.
Рисунок 2-1. SIMD-регистры с плавающей точкой.
SIMD-регистры с плавающей точкой содержат упакованные 128-разрядные данные. Команды SSE обращается к SIMD-регистрам с плавающей точкой используя регистровые имена XMM0 и до XMM7 (Рисунок 2-1). SIMD-регистры с плавающей точкой могут быть использованы для вычислений над данными; но не могут быть использованы для адресации памяти. Адресация выполняется с помощью определенных в IA режимов адресации и регистров общего назначения (EAX, EBX, ECX, EDX, EBP, ESI, EDI и ESP).
Также вводится новый регистр контроля/состояния MXCSR, он используется для маскирования и демаскирования обработки числовых исключительных ситуаций, для определения режима округления, для установки режима сброса в ноль, и для просмотра состояния флагов.
MMX регистры физически реализованы на стандартных для архитектуры Intel 80-разрядных регистрах данных с плавающей точкой. Тоесть, переход от операций MMX к операциям с плавающей точкой требует запуска команды EMMS. Но так как SIMD-регистры с плавающей точкой являются отдельным регистровым файлом, то команды MMX и команды с плавающей точкой могут быть смешаны с командами SSE без выполнение специальных инструкций таких как EMMS.
2.1.2. Тип данных SIMD с плавающей точкой.
Основной тип данных SSE это 128-разрядное значение, содержащее четыре последовательно расположенных (“упакованных”) 32-разрядных числа одинарной точности с плавающей точкой (single-precision floating-point (SPFP)) (Рисунок 2-2)
Рисунок 2-2. Упакованное простое число с плавающей точкой
Каждое 32-разрядное число с плавающей точкой имеет 1 знаковый бит, 8 битов порядка и 23 бита мантиссы, что соответствует стандарту IEEE-754 на формат представления чисел одинарной точности с плавающей запятой (SPFP-чисел).
В предшествующих поколениях процессоров Intel для внутреннего представления чисел с плавающей точкой используется 80-разрядный формат расширенной точности (архитектура х87). Этот формат сохранен и в процессоре Pentium III, однако для упакованных чисел с плавающей точкой в Pentium III используется представление в 32-разрядном формате с одинарной точностью. Поэтому в отдельных случаях результаты вычислений с плавающей точкой в архитектуре х87 могут отличаться от результатов таких же вычислений, использующих новые SIMD SPFP-команды.
Новые команды SIMD над целыми могут работать над типами данных состоящих из упакованных байт, слов или двойных слов. Новые команды предварительной выборки работают над данными размер которых от 32 байт и выше.
Команды SSE копирует упакованные типы данных (данные одинарной точности с плавающей точкой – двойные слова) в и из памяти в 64-битные или 128-битные блоки. Однако, при вычислении арифметических или логических операций над упакованными данными, SSE работает паралельно над каждым двойным словом заключенным в SIMD регистре с плавающей точкой.
Новые SIMD-команды над целыми подчиняются соглашениям принятых в инструкциях MMX и работают над данными в MMX регистрах, а не в 128-разрядных SIMD регистрах с плавающей точкой.
2.1.3. Модель выполнения SIMD
SSE использует технику Одна Команда, Несколько Элементов Данных (SIMD) для вычисления арифметических и логических операций над значениями чисел одинарной точности с плавающей точкой в 128-разрядных SIMD-регистрах с плавающей точкой. Эта техника увеличивает скорость программного выполнения с помощью паралельной обработки множественных элементов данных, использую одну инструкцию. Потоковое Расширение SIMD поддерживает операции над упакованными типами данных одинарной точности с плавающей точкой, и дополнительные SIMD команды над целыми, поддерживаются операции над упакованными типами данных (байт, слово или двойное слово).
Этот подход был выбран потому что большинство приложений обработки мультимедиа имеют следующие характеристики:
существенна паралельность;
широкий динамический уровень, отсюда базированы на переменных с плавающей точкой;
регулярное и повторяющая выборка шаблонов из памяти;
локализированные повторяющие операции выполняемые над данными;
независимый процесс управления данными.
Потоковое Расширение SIMD на 100% совметим с Стандартом IEEE 754 для двоичной арифметики с плавающей точкой. Потоковое Расширение SIMD доступно из всех режимов выполнения: Защищенного режима (Protected mode), Реально адресуемого режима (Real-address mode), и Виртуального режима 8086 (Virtual 8086 mode).
2.1.4. Формат данных в памяти
В SSE вводиться новый упакованный 128-разрядный тип данных который состоит из четырех чисел одинарной точности с плавающей точкой. 128 битов пронумерованны от 0 до 127. Бит 0 это наименьше значащий - бит (LSB), и бит 127 это наибольше значащий - бит (MSB). Байты в новом формате данных имеют последовательные адреса памяти. Порядок как всегда немного странный, тоесть байты с меньшими адресами имеют меньшее значение чем байты с старшими адресами (Рисунок 2-3).
Рисунок 2-3. Четыре упакованных данных с плавающей точкой в памяти (по адресу 1000H)
2.1.5. Формат данных SIMD регистра с плавающей точкой
Значение в SIMD регистрах с плавающей точкой имеет тот же формат, что и 128-разрядные величины в памяти. Есть два режима доступа к памяти: 128-битный и 32-битный. Тип данных соответствует формату числа одинарной точности стандарта IEEE. Таблица 2-1 показывает точность и диапазон типа данных. Кодируется только дробная часть мантисы.. Бит целого будет 1 для всех чисел, за исключением 0 и ненормированного ограниченного числа. Показатель типа данных с обычной точностью кодируется в смещенный формат.
Таблица 2-1. Точность и диапазон SIMD типа данных с плавающей точкой
Тип Данных |
Длина |
Точность
(в битах) |
Приблизительный диапазон нормированного числа |
Двоичное |
Десятичное |
С одинарной точностью |
32 |
24 |
от 2-126 до 2-127 |
от 1.18*10-38 до 1.70*1038 |
Таблица 2-2 показыват кодирование для всех классов действительных чисел (то есть, ноль, ненормированное ограниченное число, нормированное ограниченное число, и Ґ) и NaN (Not a Number - не число) для типа данных с одинарной точностью. Она также показывает формат для вещественных неопределенных значений, тоесть QNaN (Quiet NaN - "тихий NaN") и SNaN (Signalling NaN - "сигнализирующий NaN") которые используются некоторыми функциями SSE для активизации обработчика исключений.
При сохранении вещественных значений в памяти, значения с одинарной точностью сохраняются в памяти в 4 последовательных байтах. 128-битный режим доступа используется для 128-разрядной выборки из памяти, 128-разрядной пересылки между SIMD регистрами с плавающей запятой и всеми логическими, распаковки и арифметическими командами. 32-битный режим доступа используется для 32-разрядной выборки из памяти, 32-разрядной пересылки между SIMD регистрами с плавающей запятой и скалярными арифметическими командами.
Таблица 2-2. Вещественные числа и кодирование NaN
2.1.6. SIMD регистр состояния и управления
Регистр состояния и управления используется для установки флагов обнаружения арифметических исключений, флагов режимов обработки арифметических исключений, режима округления, режима flush-to-zero и для просмотра флага состояния. Содержимое этого регистра может быть загруженно с помощью инструкций LDMXCSR и FXRSTOR и сохранено в памяти с помощью инструкций STMXCSR и FXSAVE. Рисунок 2-4 показывает формат и кодирование полей в регистре MXCSR.
Рисунок 2-4. SIMD регистр состояния и управления
Биты 0-5 (поле обнаружения исключений) содержат 6 флагов, которые служат признаками детектирования арифметических SIMD исключений с плавающей точкой. Если флаг установлен в 1, то это значит, что в ходе работы обнаружено соответствующее исключение, в противном случае - нет. Эти “липкии” флаги могут быть очищенны используя инструкцию LDMXCSR для записи нулей в эти поля. Если инструкция LDMXCSR очищает битовую маску и устанавливает соответствующий бит флага иcключения, исключение не будет немедленно сгенерированно. Исключение произойдет только после следующей команды SSE. Потоковое Расширенние SIMD использует только один флаг исключения для каждой исключительной ситуации. Здесь не предоставляется возможность для уведомления об индивидуальных исключительных ситуациях внутри упакованных данных. В ситуации когда происходит несколько индентичных исключительных ситуаций в одной инструкции, соответствующий флаг исключения обновляется и указывает что хотя бы одно из этих условий произошло. По умолчанию эти флаги сбрасываются.
Биты 7-12 (поле маскирования исключений) определяют, как обрабатываются обнаруженные исключения. Если флаг установлен, то соответствующее исключение маскировано и обрабатывается процессором, который формирует приемлемый результат (в соответствии с процедурой, установленной по умолчанию) и продолжает выполнение программы. Если флаг сброшен, то вызывается программный обработчик для этого исключения. По умолчанию флаги установливаются в 1, что значит что все исключения маскированы.
Биты 13-14 (RC) устанавливают режим округления результатов при выполнении SIMD-команд над данными с плавающей точкой. По умолчанию устанавливается режим округление до ближайшего.
Бит 15 (FZ) используется для включения режима Flush To Zero. По умолчанию бит 15 установлен в 0, что выключает режим Flush To Zero.
Остальные биты регистра MXCSR (биты 16-31 и бит 6) определены как зарезервированные и установлены в 0; попытка записи не нулевых значений в эти биты, используя инструкцию FXRSTOR или LDMXCSR, вызовет исключение общего нарушения защиты (general protection exception).
2.1.7. Поле управления округлением
Поле управления округлением (RC) регистра MXCSR (биты 13 и 14) управляют как округляется результат инструкции с плавающей точкой. Поддерживается четыре режима округления: округление до ближайшего, до меньшего или равного, до большего или равного, и в сторону нуля (смотреть таблицу 2-3). Округление до ближайшего зто режим по умолчанию и он подходит для большинства приложений. Он обеспечивает наиболее точный и статистически несмещенную оценку правильного результата.
Режим округления |
Установка полей RC |
Описание |
Округление до ближайшего |
00B |
Результатом округления берется наилучшее приближение до точного результата. Если два значения одинаково близки к точному результату, то берется четное значение (то есть, то значение у которого наименьший значащий разряд установлен в ноль) |
Округление до меньшего или равного (в сторону -Ґ) |
01B |
Результат округления ближайшее, но не больше чем точное решение. |
Округление до большего или равного (в сторону +Ґ) |
10B |
Результат округления ближайшее, но не меньше чем точное решение. |
Округление в сторону нуля (усечение) |
11B |
Результат округления ближайшее, но не больше чем абсолютное значение точного решения. |
Таблица 2-3. Поле управления округлением (RC)
Режимы округления до большего и меньшого называются округлением по направлению и могут быть использованы для реализации интервальной арифметики. Интервальная арифметика используется для определения верхней и нижней границы точного решения в многошаговых вычислениях, когда промежуточный результат вычислений округляется. Режим округления в сторону нуля (иногда называется “chop” режим) обычно используется при вычислении целых.
2.1.8. Режим Flush To Zero
Если произошло исчезновение порядка (underflow), а поле flush-to-zero (FZ бит 15) регистра MXCSR установлено в 1, то процессор выполняет следующие действия:
возвращает нулевое значение в качестве результата, присваивая ему знак истинного результата
устанавливает в 1 биты 4 и 5 регистра MXCSR (флаги обнаружения исключений исчезновения порядка и неточного результата).
Указанные действия выполняются в том случае, если исключение underflow маскировано (бит 11 регистра MXCSR установлен в 1). При таком режиме увеличивается скорость работы программ, в которых часто происходит исчезновение порядка результата. Достигается это, однако, ценой снижения точности вычислений. Указанный режим работы не является согласованным с требованиями стандарта IEEE 754.
2.2. Команды Потокового Расширения SIMD
Потоковое Расширение SIMD состоит из 70 команд, сгрупированных в следующии категории:
Команды копирования данных
Арифметические команды
Команды сравнения
Команды преобразования типов данных
Логическии команды
Дополнительные целочисленные SIMD-команды
Команды перестановки
Команды управления состоянием
Команды управления кэшированием
2.2.1. Операнды команд
Потоковое расширение SIMD архитектуры Intel поддерживают два типа операций над упакованными данными с плавающей точкой - параллельные и скалярные.
Параллельные операции, как правило, действуют одновременно на все четыре 32-разрядных элемента данных в каждом из 128-разрядных операндов как это показано на Рисунке 2-5. В именах команд, выполняющих параллельные операции, присутствует суффикс ps. Например, команда addps складывает 4 пары элементов данных и записывает полученные 4 суммы в соответствующие элементы первого операнда.
Рисунок 2-5. Упакованные (Параллельные) операции.
Скалярные операции действуют на младшие (занимающие разряды 0-31) элементы данных двух операндов как это показано на Рисунке 2-6. Остальные три элемента данных в выходном операнде не изменяются (исключение составляет команда скалярного копирования movss). В имени команд, выполняющих скалярные операции, присутствует суффикс ss (например, команда addss).
Рисунок 2-6. Скалярные операции.
Большинство команд имеют два операнда. Данные, содержащиеся в первом операнде, могут использоваться командой, а после ее выполнения, как правило, замещаются результатами. Данные во втором операнде используются в команде и после ее выполнения не изменяются. Далее в тексте входным называется второй операнд, а выходным – первый.
Для всех команд адрес операнда в памяти должен быть выровнен по 16-байтной границе, кроме невыровненных команд сохранения и загрузки.
2.3. Обзор SIMD-команд
2.3.1. Команды копирования данных
Команды этой группы выполняют операции параллельного копирования упакованных элементов данных, а также скалярного копирования только младшего элемента операнда. Действия производятся над операндами, расположенными в XMM-регистрах или в памяти.
Командами параллельного копирования являются: MOVAPS, MOVUPS, MOVHPS, MOVHLPS, MOVLHPS, MOVLPS, MOVMSKPS, MOVSS.
Команда MOVAPS (Move aligned packed, single-precision, floating-point) копирует 128 бит упакованных данных из памяти в SIMD-регистр с плавающей точкой и наоборот, или между SIMD-регистрами с плавающей точкой. Линейный адрес соответствует адресу младшего байта группы данных в памяти. Обращение в память должно быть по адресу, кратному 16 байтам; в противном случае генерируется исключение.
Команда MOVUPS (Move unaligned packed, single-precision, floating-point) копирует 128 бит упакованных данных из памяти в SIMD-регистр с плавающей точкой и наоборот, или между SIMD-регистрами с плавающей точкой. Команда MOVUPS применяется для обращения к невыровненным данным в памяти.
Команда MOVHPS (Move unaligned, high packed, single-precision, floating-point) копирует 64 бита упакованных данных из памяти в два старшие элемента SIMD-регистра с плавающей точкой и наоборот. При копировании данных из памяти в SIMD-регистр, два младших элемента этого регистра не изменяются. Команда работает с адресом младшего байта группы данных в памяти.
Команда MOVHLPS (Move high to low packed, single-precision, floating-point) копирует старшие 64 бита из исходного регистра в младшие 64 бита регистра назначения. Старшие 64 бита регистра назначения не изменяются.
Команда MOVLHPS (Move low to high packed, single-precision, floating-point) копирует младшие 64 бита из исходного регистра в старшие 64 бита регистра назначения. Младшие 64 бита регистра назначения не изменяются.
Команда MOVLPS (Move unaligned, low packed, single-precision, floating-point) копирует 64 бита упакованных данных из памяти в два младшие элемента SIMD-регистра с плавающей точкой и наоборот. При копировании данных из памяти в SIMD-регистр, два старших элемента этого регистра не изменяются. Линейный адрес соответствует адресу младшего байта группы данных в памяти.
Команда MOVMSKPS (Move mask packed, single-precision, floating-point) копирует содержимое старших (знаковых) разрядов каждого из четырех FP-элементов, находящихся во входном регистре, в младшие разряды выходного целочисленного регистра, и формирует таким образом 4-битовую маску. Старшие 28 разрядов целочисленного регистра обнуляются.
Команда MOVSS (Move scalar single-precision, floating-point) копирует младшие 32 бита из памяти в SIMD-регистр с плавающей точкой или наоборот, и между регистрами. При копировании 32 битов данных из памяти в SIMD-регистр, все 96 оставшихся старших битов этого регистра обнуляются. Команда работает с адресом младшего байта группы данных в памяти.
2.3.2. Арифметические команды
Арифметические команды SIMD выполняют сложение, вычитание, умножение и деление данных одинарной точности с плавающей точкой.
Входной (второй) операнд этих команд может располагаться либо в SIMD-регистре, либо в памяти. Выходной (первый) операнд должен находиться в SIMD-регистре. Арифметические команды поддерживают как параллельные, так и скалярные операции.
2.3.2.1. Команды упакованного/скалярного сложения и вычитания
Команды ADDPS (Add packed, single-precision, floating-point) и SUBPS (Subtract packed, single-precision, floating-point) складывают или вычитают четыре пары упакованных операндов одинарной точности с плавающей точкой.
Команды ADDSS (Add scalar single-precision, floating-point) и SUBSS (Subtract scalar single-precision, floating-point) складывают или вычитают младшую пару упакованных операндов одинарной точности с плавающей точкой. Остальные элементы регистра не меняются.
2.3.2.2. Команды упакованного/скалярного умножения и деления
Команды MULPS (Multiply packed, single-precision, floating-point) и DIVPS (Divide packed, single-precision, floating-point) умножают или делят четыре пары упакованных операндов одинарной точности с плавающей точкой.
Команды MULSS (Multiply scalar single-precision, floating-point) и DIVSS (Multiply scalar single-precision, floating-point) умножают или делят младшую пару упакованных операндов одинарной точности с плавающей точкой. Остальные элементы регистра не меняются.
2.3.2.3. Команды упакованого/скалярного вычисления квадратных корней
Команды вычисления квадратных корней SQRTPS (Square root packed, single-precision, floating-point) и SQRTSS (Square root scalar single-precision, floating-point) определяют арифметические значения квадратного корня для чисел, упакованных во входной (второй) операнд, и записывают результаты в элементы выходного операнда.
Входной операнд для этих команд может располагаться либо в регистре, либо в памяти. Выходной операнд должен обязательно находиться в SIMD-регистре.
Команды вычисления квадратных корней поддерживают как параллельные, так и скалярные операции (SQRTPS и SQRTSS).
2.3.2.4. Команды упакованого/скалярного нахождения максимума и минимума
Команды нахождения минимума и максимума производят попарное сравнение соответствующих элементов двух операндов и записывают минимальные или максимальные значения в выходной операнд.
Входной операнд для этих команд может располагаться либо в XMM-регистре, либо в памяти. Выходной операнд должен обязательно находиться в XMM-регистре. Поддерживаются как параллельные, так и скалярные операции (maxps (Maximum packed, single-precision, floating-point), maxss, minps и minss).
2.3.3. Команды сравнения
Команды сравнения попарно сравнивают все четыре соответствующих FP-элемента двух операндов (для скалярного варианта команд – только младшие элементы) и проверяют выполнение арифметического условия, специфичного для каждой команды. Если для сравниваемой пары условие выполняется, то в соответствующие 32 разряда выходного операнда записывается маска из всех единиц, в противном случае – маска из нулей. Получаемая в результате двоичная маска обычно используется при логических операциях с объектами.
Входной операнд может располагаться либо в XMM регистре, либо в памяти. Выходным операндом должен быть XMM регистр (SIMD регистр).
Команды сравнения:
Команда CMPPS (Compare packed, single-precision, floating-point) сравнивает четыре пары упакованных чисел одинарной точности с плавающей точкой используя непосредственный операнд как предикат, возращает как результат в каждом поле SP все "1" (32-битовая маска) или все "0". Команда подерживает набор из 12 условий: равенство, меньше, меньше или равно, больше, больше или равно, неупорядоченно, не равно, не меньше, не меньше или равно, не больше, не больше или равно, упорядоченно.
Команда CMPSS (Compare scalar single-precision, floating-point) сравнивает младшую пару упакованных чисел использую непосредственный операнд как предикат (как и в CMPPS), возращает как результат в младшем поле SP 32-битовую маску из всех "1" или всех "0".
Команда COMISS (Compare scalar single-precision, floating-point ordered and set EFLAGS) сравнивает младшую пару упакованных чисел, и устанавливает флаги ZF, PF, и CF в регистре флагов EFLAGS (флаги OF, SF, и AF сбрасываются).
Команда UCOMISS (Unordered compare scalar single-precision, floating-point ordered and set EFLAGS) сравнивает младшую пару упакованных чисел, и устанавливает флаги ZF, PF, и CF в регистре флагов EFLAGS (флаги OF, SF, и AF сбрасываются).
2.3.4. Команды преобразования типов данных
Команды этой группы выполняют преобразования данных из 32-разрядного целочисленного представления со знаком в FP-представление и обратно. Эти комады производят преобразование упакованных и скалярных данных между 128-битными SIMD регистрами с плавающей точкой и также с 64-битными целыми MMX регистрами или 32-битными целыми регистрами IA32. Упакованная версия работает также как и команды MMX, при наличии команд x87-FP, включает:
Переход из x87-FP в MMX технологию (TOS=0).
Команды MMX записывают единицы в разряды порядка соответствующего регистра x87-FP.
Использование EMMS для перехода из MMX технологии в x87-FP.
Команда CVTPI2PS (Convert packed 32-bit integer to packed, single-precision, floating-point) преобразует два 32-битных знаковых числа в регистре MMX в два младших числа одинарной точности с плавающей точкой. Когда преобразование неточны, то возвращается округленное значение соответствующее режиму округления в регистре MXCSR. Старшие два числа регистра назначения не изменяются.
Команда CVTSI2SS (Convert scalar 32-bit integer to scalar single-precision, floating-point) преобразует 32-битное знаковое целое в регистре MMX в младшее число SIMD-регистра. Когда преобразование неточны, то возвращается округленное значение соответствующее режиму округления в регистре MXCSR. Старшие три числа регистра назначения не изменяются.
Команда CVTPS2PI (Convert packed, single-precision, floating-point to packed 32-bit integer) преобразует два младших числа одинарной точности с плавающей точкой SIMD-регистра в два 32-битных знаковых целых регистра MMX. Когда преобразование неточны, то возвращается округленное значение соответствующее режиму округления в регистре MXCSR.
Команда CVTTPS2PI (Convert truncate packed, single-precision, floating-point to packed 32-bit integer) аналогична CVTPS2PI, за исключением того что если преобразования неточны, то в этом случае возвращается усеченый результат.
Команда CVTSS2SI (Convert scalar single-precision, floating-point to a 32-bit integer) преобразует младшее число SIMD регистра в 32-битное знаковое целое регистра IA (в стандартные регистры). Когда преобразование неточны, то возвращается округленное значение соответствующее режиму округления в регистре MXCSR.
Команда CVTTSS2SI (Convert truncate scalar single-precision, floating-point to scalar 32-bit integer) аналогична CVTSS2SI, за исключением того что если преобразования неточны, то в этом случае возвращается усеченый результат.
2.3.5. Логические команды
Команды этой группы выполняют поразрядные логические операции над упакованными SPFP-элементами.
В группу входят команды andps, andnps, orps и xorps.
Логические команды часто используются для:
вычисления абсолютной величины (модуля) чисел;
изменения знакового разряда (инверсии знака);
действий с маской из нулей и единиц, получаемой в операциях сравнения.
Команда ANDPS (Bit-wise packed logical AND for single-precision, floating-point) возвращает результат выполнения поразрядного AND между двумя операндами.
Команда ANDNPS (Bit-wise packed logical AND NOT for single-precision, floating-point) возвращает результат выполнения поразрядного AND NOT между двумя операндами.
Команда ORPS (Bit-wise packed logical OR for single-precision, floating-point) возвращает результат выполнения поразрядного OR между двумя операндами.
Команда XORPS (Bit-wise packed logical XOR for single-precision, floating-point) возвращает результат выполнения поразрядного XOR между двумя операндами.
2.3.6. Дополнительные команды SIMD над целыми
Аналогично командам технологии MMX, новые SIMD-команды обработки целочисленных данных:
Выполняют SIMD-операции над несколькими целочисленными элементами данных, упакованными в 64-разрядные группы.
Загружают и хранят упакованные данные в 64-разрядных MMX-регистрах (отдельно от 128-разрядных XMM-регистров данных с плавающей запятой).
Мнемоника имен новых целочисленных SIMD-команд включает префикс и суффиксы, указывающие на характер выполняемой операции и тип используемых данных:
Префикс p указывает на то, что команда выполняет параллельные операции над несколькими элементами данных;
Суффиксы b,w,d и q указывают на используемый тип данных;
Суффиксы u или s указывают на использование данных со знаком или без знака, соответственно.
Так, например, команда умножения pmulhuw работает с данными типа “упакованные 16-разрядные слова без знака”.
Команды PAVGB/PAVGW (Average unsigned source sub-operands, without incurring a loss in precision) сложения безнаковых элементов данных опреанда источника с безнаковыми элементами данных регистра назначения. Потом результат сложения каждого элемента независимо сдвигается вправо на один бит. Старшие биты каждого элемента заполняются битами переноса суммы. Для предотвращения накопления ошибок округления, выполняется усреднение. Младший бит каждого окончательного сдвинутого результата устанавливается в 1 если два младших бита промежуточной несдвинутой суммы были равны 1.
Команда PEXTRW (Extract 16-bit word from MMX register) копирует слово из регистра MMX определенного двумя младшими битами 8-разрядного непосредственного операнда в младшее слово 32-разрядного целочисленного регистра; все 16 старших разрядов выходного регистра обнуляются.
Команда PINSRW (Insert 16-bit word into MMX register) копирует младшее 16-разрядное слово из 32-разрядного целочисленного регистра (или 16 разрядов данных из памяти) в одно из слов MMX регистра, определенное значением двух младших разрядов 8-разрядного непосредственного операнда.
Команды PMAXUB/PMAXSW (Maximum of packed unsigned integer bytes or signed integer words) копирует максимум каждой пары упакованных элементов данных в регистр назначения.
Команды PMINUB/PMINSW (Minimum of packed unsigned integer bytes or signed integer words) копирует минимум каждой пары упакованных элементов данных в регистр назначения.
Команда PMOVMSKB (Move Byte Mask from MMX register) копирует старшие (знаковые) биты всех восьми упакованных байтов входного операнда - MMX регистра и формирует 8-разрядную маску в младших разрядах 32-разрядного целочисленного регистра. Все старшие 24 разряда выходного целочисленного регистра обнуляются.
Команда PMULHUW (Unsigned high packed integer word multiply in MMX register) попарно перемножает четыре 16-разрядных слова без знака входного и выходного операндов (регистра MMX), что дает четыре 32-разрядных промежуточных произведения без знака. Старшие 16 разрядов произведений записываются в 16-разрядные слова выходного операнда. Младшие 16 разрядов промежуточных произведений теряются.
Команда PSADBW (Sum of absolute differences) вычисляет абсолютную разность для каждой пары байтовых под-операндов регистра иточника, и затем суммирует эти восемь разностей в один 16-битный результат.
Команда PSHUFW (Shuffle packed integer word in MMX register) выбирает четыре 16-разрядных слова (не обязательно различных) из входного операнда и записывает их в определенном порядке в выходной операнд. Порядок записи слов задается 2-разрядными полями 8-разрядного непосредственного операнда. Входной операнд может располагаться либо в MMX регистре, либо в памяти. Выходной операнд должен находиться в MMX-регистре.
2.3.7. Команды перестановки
Команда SHUFPS (Shuffle packed, single-precision, floating-point) выбирает по два из четырех элементов каждого операнда. Два выбранных элемента первого операнда копируются в младшие элементы выходного операнда, а два выбранных элемента второго операнда – в старшие элементы выходного операнда (см. рисунок 2-7). Выборка элементов для копирования производится в соответствии со значением 8-разрядного непосредственного операнда.
Входной (второй) операнд может располагаться либо в XMM регистре, либо в памяти. Выходной (первый) операнд должен обязательно находиться в XMM регистре.
Рисунок 2-7. Упакованная команда перестановки.
Команда UNPCKHPS (Unpacked high packed, single-precision, floating-point) копирует по два старших элемента каждого из операндов в выходной операнд, причем расставляет их, помещая через один (см. рисунок 2-8). Нижняя половина входных операндов игнорируется. Если входной операнд берется из памяти, то хотя в операции участвует только 64-разрядная группа данных, считывается из памяти все 128-бит операнда.
Рисунок 2-8. Операция распоковки старших элементов.
Команда UNPCKLPS (Unpacked low packed, single-precision, floating-point) выполняет те же действия с двумя парами младших элементов каждого их операндов (см. рисунок 2-9).
Рисунок 2-9. Операция распоковки младших элементов.
2.3.8. Команды управления состоянием
Команда STMXCSR (Store SIMD Floating-Point Control and Status Register) служит для сохранения содержимого регистра MXCSR в памяти, а команда LDMXCSR (Load SIMD Floating-Point Control and Status Register) - для загрузки этого содержимого из памяти.
Обычно к команде LDMXCSR прибегают, когда хотят сбросить флаги обнаружения арифметических исключений в регистре MXCSR.
Команда FXSAVE сохраняет в памяти компоненты состояния процессора Pentium III (регистр состояния FP, регистр состояния MMX и регистры SIMD), когда операционная система осуществляет переключение контекста.
Команда FXRSTOR восстанавливает компоненты состояния процессора Pentium III из памяти. Информация о компонентах состояния процессора для этих команд хранится в области памяти размером 512 байт. Задаваемый адрес памяти должен быть выровнен на 16 байт.
2.3.9. Команды управления кэшированием
Данные определенные программистом могут иметь временную (за короткий промежуток времени программа обращается к одной и той же ячейке памяти большое число раз) или пространственную (программа последовательно обращается к ячейкам памяти с близкими друг к другу адресами, например, если программа обрабатывает логически однородные данные (скажем, элементы массива), причем каждое следующее обращение наиболее вероятно к элементу, смежному с предшествующим) локализацию. Те данные, к которым программа обращается нерегулярно и через значительные интервалы времени, являются данными со слабой локализацией. Примером может являться набор данных, описывающих трехмерный объект, если обращение к каждой вершине этого набора происходит только один раз при генерации очередного кадра. Таким образом, программист не хочет чтоб кэшированный код и данные приложения были перезаписаны данными со слабой локализацией.
В архитектуре процессора Pentium III вводится совокупность команд нового типа, обеспечивающих:
Управление кэшированием данных с целью минимизации “засорения” кэш-памяти и сокращения числа обращений на запись в основную память;
Упреждающее кэширование данных с целью организации параллельной работы конвейера обработки и операций по доступу в память, и уменьшения за счет этого задержек, связанных с работой памяти.
2.3.9.1 Некэширующие команды записи в память
Некэширующие команды предназначены для записи слабо локализованных данных непосредственно в основную память, минуя кэш-память. Такая технология уменьшает "засорение" кэш-памяти ненужными данными, а также вытеснение из нее кэшированных данных с временнóй или пространственной локализацией.
Команда MOVNTPS (Non-temporal store of packed, single-precision, floating-point) записывает 128 бит SPFP-данных непосредственно в память и не кэширует данные при кэш-промахе (cache miss). При кэш-попадании (cache hit) данные в кэше обновляются, а прямой записи в память НЕ происходит.
Команда MOVNTQ (Non-temporal store of packed integer in an MMX register) записывает 64 бита целочисленных данных непосредственно в память и не кэширует данные при кэш-промахе. При кэш-попадании данные в кэше обновлются, а прямой записи в память НЕ происходит
Команда MASKMOVQ (Non-temporal byte mask store of packed integer in an MMX register) выборочно записывает байты из MMX-регистра непосредственно в память. Байты выбираются в соответствии с 8-разрядной маской, состоящей из старших битов в байтах второго операнда - MMX-регистра. Единица в некотором разряде маски означает запись соответствующего байта в память, нуль - отсутствие записи. Адрес памяти, по которому производится запись, указывается в регистре EDI.
Эти команды не переносят данные в кэш вышестоящего уровня при записи (режим записи non-write allocate), тоесть сохраняемые данные записываются только в кэш соответствующего уровня (если эти данные уже кэшированы ранее), или только в память (если данные не кэшированы). Одновременного переноса сохраняемых данных в кэш вышестоящего уровня ("ближе" к процессору) не происходит. Такой режим записи полезен при работе с данными, доступ к которым осуществляется нерегулярно. Предотвращается "засорение" кэш-памяти и лишние пересылки по шине. Для них характерны особенности, аналогичные работе в режиме записи с буферизацией, в частности, слабая упорядоченность обращений в память на запись.
2.3.9.2 Упреждающее кэширование
Команды этой группы позволяют кэшировать нужные данные заранее. За счет этого уменьшаются задержки, связанные с доступом к основной памяти. Рассматриваемые команды не влияют на ход выполнения программы с функциональной точки зрения.
Обеспечивается возможность записи данных в кэш-память различных уровней. Имена команд кэширования содержат суффиксы, указывающие нужный уровень кэш-памяти.
Команды prefetcht0, prefetcht1 и prefetcht2 предназначены для кэширования часто используемых данных (с временной или пространственной локализацией).
Команда prefetcht0 записывает кэшируемые данные из памяти в кэш всех уровней (L1 и L2 в архитектуре процессора Pentium III).
Команды prefetcht1 и prefetcht2 в архитектуре процессора Pentium III записывают кэшируемые данные из памяти в кэш L2.
Команда prefetchnta записывает кэшируемые данные из памяти в кэш для данных со слабой локализацией. В архитектуре процессора Pentium III данные обходят L2-кэш и переносятся в L1-кэш, используемый для этих целей.
2.3.9.3 Принудительная запись
Команда SFENCE (Store Fence) применяется для строгого упорядочения последовательности обращений в память и синхронизации ее с содержимым кэш-памяти, если такие обращения являются слабо упорядоченными.
При использовании SFENCE в основную память копируются все данные предшествующих команд записи, хранящиеся в буфере записи и кэше. Только после этого будут выполняться следующие команды записи.
Команда SFENCE временно блокирует выполнение лишь последующих команд сохранения данных, не влияя при этом на работу других команд.
3. Примеры программирования с помощью SSE
3.1. Проверка наличия процессорной поддержки
Для выполнения новых SIMD-команд требуется поддержка со стороны процессора и операционной системы.
Прикладная программа может использовать новые команды процессора Pentium III только в том случае, если выполнены следующие условия:
CR0.EM (бит 2) содержит нулевое значение;
CR4.OSFXSR (бит 9) установлен в единицу (нужно, для подтверждения поддержки со стороны операционной системы новых регистров процессора Pentium III при переключении контекста);
CPUID.XMM (бит 25 регистра EDX) установлен в единицу (нужно, для подтверждения процессорной поддержки всех новых команд процессора Pentium III, программа должна выполнить команду CPUID с eax=1 и проверить, результат бита CPUID.XMM (бит 25 регистра EDX)).
Если это условие нарушено, то новые команды (за исключением команд упреждающей выборки prefetch и принудительной записи sfence) будут генерировать исключение недопустимого кода операции (Int 6).
Следующий код служит для проверки поддержки новых SIMD-команд со стороны процессора:
boolean Streaming_SIMD_Extensions = TRUE
try {
IssueStreamingSIMDExtensionsload();
}
except (UNWIND) {
Streaming_SIMD_Extensions = FALSE
}
Следующий код служит для проверки поддержки немаскированных исключений со стороны операционной системы:
boolean unmasked_work = TRUE
try {
IssueUnMask();
}
except (UNWIND) {
unmasked_work =FALSE
}
3.2. Скалярное произведение векторов
При вычислениях с векторными величинами нередко требуются горизонтальные операции, как, например, суммирование всех компонент вектора. Примером может служить скалярное произведение векторов.
Приведенный фрагмент кода иллюстрирует применение новых SIMD-команд для вычисления скалярного произведения двух 4-компонентных векторов A и B. Результирующее значение скалярного произведения формируется сразу во всех четырех элементах XMM-регистра.
Следующий код служит для вычисления скалярного произведения двух 4-компонентных векторов:
movaps xmm0, [Vector1] ;Загрузить первый вектор: a3,a2,a1,a0
mulps xmm0, [Vector2] ;умножить покомпонентно на второй
;f3=a3*b3,f2=a2*b2,f1=a1*b1,f0=a0*b0
movaps xmm1, xmm0; ;Копировать результаты
shufps xmm1, xmm1, 4Eh; ;Переставить: f1,f0,f3,f2
addps xmm0, xmm1; ;Сложить: f3+f1,f2+f0,f1+f3,f0+f2
movaps xmm1, xmm0; ;Копировать результаты
shufps xmm1, xmm1, 11h; ;Переставить: f0+f2,f1+f3,f0+f2,f1+f3
addps xmm0, xmm1; ;Сложить: f0+f1+f2+f3,f0+f1+f2+f3,
f0+f1+f2+f3,f0+f1+f2+f3
; Результат во всех элементах xmm0
; end
3.3. Умножение матрицы на вектор
Операция умножения матрицы на вектор является одной из основных в приложениях, связанных с преобразованиями 3D объектов
Следующий код служит для умножения матрицы 4х4 на каждый из четырех
заданных векторов (вершин объекта).
; ecx = Служит счетчиком цикла (по 4 вершины за цикл)
; esi = Указывает на начальный адрес матрицы
; list = Указывает на начальный адрес данных в структуре SOA (модель SOA задает последовательное расположение в памяти одноименных компонент (например, x0, x1, x2,…,xn ) для различных вершин объекта )
; X, Y, Z и W являются смещениями соответствующих массивов в структуре.
movaps xmm0, [list+X+ecx] ;загрузить x-компоненты
movaps xmm2, [list+Y+ecx] ;загрузить y-компоненты
movaps xmm3, [list+Z+ecx] ;загрузить z-компоненты
movaps xmm1, [esi+m00] ;m00 m00 m00 m00
movaps xmm4, [esi+m01] ;m01 m01 m01 m01
mulps xmm1, xmm0 ;x*m00 x*m00 x*m00 x*m00
mulps xmm4, xmm2 ;y*m01 y*m01 y*m01 y*m01
addps xmm4, xmm1 ;сложить полученные результаты
movaps xmm1, [esi+m02] ;m02 m02 m02 m02
mulps xmm1, xmm3 ;z*m02 z*m02 z*m02 z*m02
addps xmm4, xmm1 ;сложить полученные результаты
addps xmm4, [esi+m03] ;добавить последний элемент строки матрицы
;конец умножения строки
; повторить для всех строк матрицы.
; end
3.4. Приближенное нахождение обратных значений
Команды приближенного определения обратных значений выполняются быстрее, чем операции деления для чисел с плавающей запятой и нахождения квадратного корня. Однако погрешность вычислений при этом увеличивается.
Предлагаемые фрагменты кода решают задачу нахождения обратного значения для числа с плавающей запятой тремя разными способами. Использование приближенной команды rcpps (первый пример) дает максимальную скорость при наименьшей точности. Во втором примере (rcpps с NR) для увеличения точности результата применяется алгоритм Ньютона-Рафсона (если надо повысить точность величины rcpps(a), обратной к a, то алгоритм Ньютона-Рафсона дает следующее выражение: x = 2*rcpps(a) – a*rcpps(a)2). В третьем примере выполняется SIMD-команда деления, что обеспечивает наивысшую точность результата ценой снижения производительности.
Определим следующие константы:
; INIT9 = [9,9,9,9]
; One = 1
; Приближенное определение 1/9 с помощью команды rcpps
movaps xmm0, [INIT9]
rcpps xmm1,xmm0 ; xmm1 = 9; xmm1 = ~1/9
; Уточнение результата по методу Ньютона-Рафсона
mulps xmm0,xmm1 ;xmm0 = 9 * ~1/9
mulps xmm0,xmm1 ;xmm0 = 9 * ~1/9 * ~1/9
addps xmm1,xmm1 ;xmm1 = 2 * ~1/9
subps xmm1,xmm0 ;xmm1 = 2 * ~1/9 - 9 * ~1/9 * ~1/9
; Деление командой divps
movaps xmm0,[INIT9]
movaps xmm3,[One]
divps xmm3,xmm0 ;xmm3 = a; xmm0 = 1/9
3.5. Устранение ветвлений
В приведенном ниже фрагменте программы на языке C выполняется сравнение с нулем каждого из четырех FP–чисел в XMM-регистре:
if(xmm[i]>0)
xmm[i]=xmm[i]+1.
else
xmm[i]=xmm[i]-1.
Если условие выполнено, значение увеличивается на 1; в противном случае – уменьшается на 1.
Эквивалент этого фрагмента на языке ассемблера показан ниже. В нем выполняются SIMD SPFP-команды сравнения и логических операций, причем ветвление полностью устранено. Если использовать скалярный код IAх87, то для аналогичных действий потребовались бы четыре команды сравнения и условного перехода.
Определим следующие константы:
;One = [1,1,1,1]
;MinusOne = [-1,-1,-1,-1]
;Zero = [0,0,0,0]
;Convert= [9.58682, -34.5567, -0.555, 0.2345]
movaps xmm3,[One]
movaps xmm4,[MinusOne]
movaps xmm0,[Convert]
movaps xmm1,xmm0
cmpltps xmm0,[Zero]
andps xmm4,xmm0
andnps xmm0,xmm3
addps xmm1,xmm4
addps xmm1,xmm0
; end
3.6. Преобразование из FP в целое
В расчетах освещенности 3D-объектов и во многих других задачах целесообразно использовать новые SIMD-команды для обработки данных с плавающей запятой. Поскольку графические адаптеры считывают только целочисленные данные, то при выводе результатов расчета на экран дисплея необходимо преобразовать полученные результаты расчета из FP-представления в целое.
Этот код выполняет преобразование четырех SPFP-чисел XMM регистра в целые числа двух MMX регистрах.
Определим следующие константы:
;Convert
movaps xmm0,[Convert]
cvttps2pi mm0, xmm0
shufps xmm0,xmm0,Eh
cvttps2pi mm1, xmm0
; end
3.7. Упреждающее кэширование
Команды, загружающие данные из основной памяти в кэш-память, могут блокировать выполнение других операций и снизить быстродействие программы. С помощью команд упреждающего кэширования данных можно компенсировать эти задержки и повысить производительность.
Этот код уменьшает задержки за счет использования команды prefetch.
loop
movaps xmm1, [edx + ebx]
movaps xmm2, [edx + ebx + 16]
prefetcht1 [edx + ebx + 32] ;Кэшировать данные заранее
;...
add ebx,32
cmp ebx, buff_size
jl loop
Литература:
1. Руководству программиста по архитектуре Intel, Том 1. (Intel Architecture Software Developer's Manual, Volume 1: Basic Architecture)
2. Руководству программиста по архитектуре Intel, Том 2. (Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual)
3. Руководству программиста по архитектуре Intel, Том 3. (Intel Architecture Software Developer's Manual, Volume 3: System Programming Guide).
|