Как стать автором
Обновить

Комментарии 11

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

Здесь ответ очевиден — переход не самая удачная идея, поскольку не слишком хорошо сочетается с конвейером. Но есть еще и вариант с условным исполнением команд, и он вполне приемлем

Есть мнение, что ситуация ровно обратная. Условные переходы предсказываются задолго до попадания операций в вычислительный конвеер и как правило с очень хорошей точностью. А вот команды с предикатами, как в том же 32-битном арме -- это ад с т.з. структуры конвеера. Начиная с необходимости +1 порта чтения у регистрового файла (регистр-приёмник может или записаться или нет только в простом несуперскалярном единственном конвеере как у arm7tdmi, а во "взрослой" суперскалярной архитектуре это будет дополнительный операнд у команды) и кончая всеми теми милыми приколами, когда предикатная операция решит записать в pc. Ну и конечно же, дополнительные зависимости по флагам, что отнюдь не облегчает шедулинг.

Поскольку в статье идет речь о RISC-V, то наверное стоит посмотреть на RISC-V и в этом вопросе. Ратифицированное расширение Zicond вводит ровно два опкода:

  • czero.eqz rd, rs1, rs2 -- Moves zero to a register rd, if the condition rs2 is equal to zero, otherwise moves rs1 to rd

  • czero.nez rd, rs1, rs2 -- Moves zero to a register rd, if the condition rs2 is nonzero, otherwise moves rs1 to rd

Все остальное делается набором команд (к примеру, тернарный оператор `cond ? a : b` делается тремя операциями).

PC нет в gpr (имхо возможность писать - да и даже читать - PC обычными операциями - это красиво в чистой ISA, но "ад с т.з. конвеера"), флагов нет, никаких лишних портов чтения, никакой неявной зависимости от rd (как у cmove) и вообще никаких дополнительных зависимостей нет помимо стандартных двух. Фактически это обычные операции АЛУ, ничем архитектурно не отличающиеся от, например, add - и исполняться они будут так же быстро, не затыкая конвейер.

расширение Zicond вводит ровно два опкода

Каковые могут жить с 2 портами чтения регистрового файла пока конвеер простой и один. Как только эти команды начинают работать на суперскалярном процессоре, СРАЗУ ЖЕ появляется зависимость от rd: его всегда необходимо читать и всегда писать. По-другому суперскаляры не умеют.

обычные операции АЛУ, ничем архитектурно не отличающиеся от, например, add

Отличающиеся. Тем, что или rd обновляется не всегда (простой конвеер) или rd является одним из операндов (суперскаляр).

> Отличающиеся. Тем, что или rd обновляется не всегда (простой конвеер) или rd является одним из операндов (суперскаляр).

Посмотрите еще раз на описание команд, пожалуйста. Более внимательным образом. Это НЕ предикатные команды, а другие команды, призванные решать ту же задачу (а именно - заменять условные переходы обхода пары-тройки простых команд на последовательность команд без условных переходов).

Язык С долго ругали за то, что в нем нет встроенного способа контролировать флаги переполнения. Чтобы было не так обидно, стали продвигать архитектуру, где их нет. Как-то так?

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

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

А еще при поддержке macro-op fusion две последовательные команды add/sltu могут быть слиты и исполнены за один такт как команда "сложения и взятия флага". Фактически мы получем команду addc. Но это отдается на откуп разработчикам микроархитектуры.

 так как устраняет лишние зависимости.

На современных процессорах отдельные биты флагов в OoO логике трекаются отдельно, остаются только реальные зависимости.

Также читал где-то, что флаги создают проблемы для виртуализации.

Уотерман в диссере упоминал, но там проблемы конкретно с x86 архитектурой, когда в одном регистре флагов смешали арифметику/логику и системное состояние (причём проблемы были только у программной виртуализации до появления VT). Можно просто раскидать по разным регистрам.

Фактически мы получем команду addc.

Только надо ещё этот флаг дотащить до потребителя sltu (при том, что в архитектурном состоянии он не светится) - но согласен, что это вполне реально. Та же пара compare+branch на "традиционных" процессорах сейчас фьюзится в один uop, эквивалентный команде на RISC V.

Флаги помимо виртуализации (которая действительно часто решается аппаратно) создают огромные проблемы для эмуляции архитектуры на другой архитектуре. Поскольку в 99% случаев значение флага после операции не используется, но их все надо вычислить (в худшем случае - простая эмуляция - после каждой АЛУ операции, в лучшем - продвинутый JIT - на границе транслированного базового блока). А вычисление флагов может стоить значительно дороже, чем сама операция. Даже при эмуляции x86 на arm или наоборот, где флаги в основном совпадают, с ними есть проблемки (https://fex-emu.com/FEX-2409/).

огромные проблемы для эмуляции архитектуры на другой архитектуре

Это точно не входит в приоритеты разработчиков архитектур.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации