<<<предыдущий список следующий>>>

Это - копия документа, находившегося на http://dz.ru. Авторские права, если не указано иначе, принадлежат Дмитрию Завалишину и/или Евгении Завалишиной. Все изменения, внесенные мной, находятся в этой рамочке.Пожалуйста, прочитайте disclaimer.


20 января

Продолжаем о Крузо - новом процессоре от Трансмета.

Я уже говорил о code morphing software - низкоуровневом трансляторе кодов команд x86 в "родной" исполняемый код процессора. Из описаний конкретных моделей процессора удалось выяснить, что объём транслятора не превышает мегабайта (таков размер ПЗУ/флэша, из которого процессор загружается), а для работы он требует от восьми до шестнадцати мегабайт - соответственно, 7-15 из них идут под кеширование странслированных фрагментов.

Предположительно, эта оценка приведена для среднего случая - основное ОЗУ (то, которое остаётся для ОС) - 24-64 мегабайта. Вероятно, большой объём ОЗУ потребует и большего кеша. Таким образом, трансляция приводит к удорожанию системы на несколько десятков долларов - вряд ли стоит считать крупным минусом, но и скидывать со счетов нельзя.

С другой стороны, трансляция позволяет, к примеру, более точно и масштабно предсказывать "срабатывание" условных переходов (выполнять т.н. branch prediction). Впрочем, у меня нет уверенности в том, что этот плюс реально даст хотя бы процент прироста быстродействия.

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

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

Есть ещё память. Команду запись в память нельзя менять местами с командой считывания - они могут ссылаться на одни и те же адреса и если так - от перемены мест логика работы программы нарушится. Однако менять местами их очень даже часто хочется. Кроме того, пересечения по адресам случаются не так уж и часто, и рискнуть - дело стоящее. И вполне возможное - Крузо позволяет при считывании из памяти поставить на адрес, по которому произошло обращение, метку. Теперь если последующая операция записи обратится по тому же адресу - случится исключительная ситуация, и придётся исправлять положение. Это позволяет переносить команды считывания, располагая их ранее команд записи.

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

Менее тривиален, хотя и очевиден, механизм, который позволяет избавиться от третьей взаимозависимости между командами кода. Зависимость эта обусловлена тем, что в x86 существует понятие исключительной ситуации. Пример такой ситуации - доступ по несуществующему адресу. Или попытка исполнения привилегированной команды из непривилегированного контекста. Проблемой является тот факт, что исключительная ситуация предполагает, что все команды до текущей полностью выполнены, а ни одна команда из последующих не выполнена вообще. Очевидно, что при переставлении команд местами выполнить это условие оказывается нелегко. Если случилась исключительная ситуация, а часть команд, идущих в оригинальном, 86-м коде после неё мы уже поспешили исполнить? Нужно откатить всё назад - отменить результат исполнения.

В Крузо это возможно! В процессоре есть запасная копия всех регистров - перед запуском странслированного блока команд на исполнение в неё переносится содержимое основного набора регистров, после чего начинается исполнение. Если в процессе встретилось исключение, чтобы не гадать, где оно всё состояние регистров восстанавливается из копии и код исполняется снова - на этот раз без перестановок, строго последовательно.

Хорошо - это регистры. А если происходила запись в память? Не проблема - она выполняется не в память, а в специальный буфер, и ждёт там, пока не будет получена команда "завершения транзакции", если можно так сказать. Она заканчивает блок странслированных команд и если исполнение добралось до неё - значит исключений не было и можно считать всё выполненным.

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

Кстати, при условии прямой компиляции из исходного текста в родной код Крузо эту проблему можно существенно ослабить. Интересно, будет ли выпущен native Crusoe Linux? Или хотя бы двухрежимный - способный исполнять x86-е программы, но сам скомпилированный под Crusoe?

Интересное решение применено в Крузо с целью избежать лишних команд условного перехода. Напомню, каждая такая команда сбивает конвейер процессора, заставляя его "оступаться" на бегу и переходы стараются как-нибудь уконтрапупить, даже ценой некоторого роста кода. Окупается.

В Мерсе... Итаниуме есть предикаты - флаги, с которыми можно ассоциировать команды. Флаг стоит - команда исполняется. "Лежит" - команда не исполняется. В Крузо - свой, достаточно изящный вариант.

Вместо (иллюстрирую на C)

if( a > b )	c = 10+a;
else		c= 10+b;

транслятор Крузо генерирует код вида

c1=10+a; c2=10+b;
c = (a > b) ? c1 : c2;

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

Всё. Наверное, более ничего существенного, исходя из имеющихся материалов, сказать про "пузо" Крузо невозможно.

Резюме: процессор интересен, но ничего сверхъестественного в нём нет. Технология преобразования двоичного кода ещё более интересна, причём интересна даже в отрыве от самого процессора.

О рыночных перспективах Крузо всерьёз говорить рано, но мне нравится наличие чёткой стратегии и ориентация на совершенно определённый сегмент рынка - носимые компьютеры. Ноутбуки. Обычно такая чёткая направленность говорит о продуманной маркетинговой политике и высокой вероятности успеха.

Оптовые закупки в компании Бюрократ!

Кстати, о мобильном компьютинге. Объявленные модели процессоров обладают в этом плане симпатичными свойствами. Во-первых, на борту процессоров расположены контроллеры памяти и PCI, что резко упрощает дизайн ноутбука. Во-вторых, они умеют не только плавно сбрасывать тактовую частоту, если загрузка заметно упала, но одновременно и понижать напряжение питания - ведь при низкой частоте и питание нужно более низкое. Это позволяет снижать энергопотребление пропорционально кубу (частота, напряжение, ток) снижения загрузки CPU. Неплохо - в качестве бонуса! :-)

Очевидное решение:

   
From: NuMoK
Subject: Crusoe

Hi.

"На базе Крузо, между прочим, можно построить нетривиальный вариант ассиметрично-двухпроцессорной машины. Один процессор будет транслировать код, другой - исполнять. Очевидно, что первый будет загружен не на 100%,..." поэтому есть смысл сбалансировать загрузку добавлением второго иполняющего процессора или понижением тактовой частоты транслирующего. Можно воспользоваться и тем, и другим способом, и получить конфигурации для разных рынков.

--
NuMoK
aka
guHo3ABP

 

Интересно - а не имеет ли смысла хранить оттранслированные копии на диске? То есть позволить ОС увидеть нутро процессора и проучаствовать в процессе трансляции?

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

Конечно, шедевр этим инструментом не снять, но, думается мне, бит так 5-6 на точку и один-два кадра в секунду извлечь - не проблема. :-)

Нет, наш человек это придумал - русский в душе. :-)