Гениальность микропроцессоров RISC-V

Автор оригинала: Erik Engheim
  • Перевод
image

Войны между RISC и CISC, проходившие в конце 1990-х, уже давно отгремели, и сегодня считается, что разница между RISC и CISC совершенно не имеет значения. Многие заявляют, что наборы команд несущественны.

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

Недавно я подробнее изучил информацию об архитектуре набора команд (instruction-set architecture, ISA) RISC-V и вот некоторые из аспектов, которые по-настоящему впечатлили меня в ISA RISC-V:

  1. Это небольшой и простой в изучении набор команд RISC. Очень предпочтителен для тех, кому интересно получать знания о микропроцессорах.
  2. Благодаря своей простоте, открытости и связи с университетскими профессорами он с большой вероятностью будет доминировать как архитектура, выбираемая для обучения процессорам в вузах.
  3. Его продуманная структура позволяет разработчикам CPU создавать высокопроизводительные микропроцессоры на основе ISA RISC-V.
  4. Благодаря отсутсвию лицензионных отчислений и нацеленности на простую аппаратную реализацию увлечённый любитель может, в принципе, создать за приемлемое время собственную конструкцию процессора RISC-V.

Месть RISC


Когда я начал понимать RISC-V лучше, то осознал, что RISC-V оказался радикальным возвратом к тому, что многие считали давно прошедшей эпохой вычислений. С точки зрения конструкции, RISC-V подобен перемещению на машине времени к классическому Reduced Instruction Set Computer (RISC, «компьютеру с набором коротких команд») начала 80-х и 90-х.

В последние годы многие заявляли, что разделение на RISC и CISC больше не имеет смысла, поскольку в процессоры RISC наподобие ARM добавили так много команд, и при этом многие из них довольно сложны, что на текущем этапе это скорее гибрид, чем чистый процессор RISC. Похожие рассуждения применялись и к другим процессорам RISC, например, PowerPC.

RISC-V же, напротив, является действительно «хардкорным» представителем процессоров RISC. Если вы почитаете в Интернете обсуждения RISC-V, то найдёте людей, утверждающих, что RISC-V был разработан какими-то олдскульными RISC-радикалами, отказывающимися двигаться в ногу со временем.

Бывшая инженер ARM Эрин Шеперд несколько лет назад написала интересную критику RISC-V:

ISA RISC-V слишком стремился к минимализму. В нём есть сильный упор на минимизацию количества команд, нормализацию кодирования и т.д. Это стремление к минимализму привело к ложным ортогональностям (например, использованию одной и той же команды для ветвления, вызовов и возвратов) и требованию избыточных команд, влияющих на плотность кода с точки зрения размера и количества команд.

Вкратце приведу немного контекста. Малый размер кода даёт преимущество в производительности, поскольку так проще хранить выполняемый код внутри высокоскоростного кэша процессора.

Критика здесь заключается в том, что проектировщики RISC-V слишком сосредоточились на обеспечении малого набора команд. В конце концов, это ведь одна из исходных целей RISC.

По словам Эрин, следствием этого стало то, что реальной программе для выполнения задач потребуется гораздо больше команд, то есть она займёт больше места в памяти.

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

Сжатие команд и Macro-Operation Fusion


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

  • Сжатые команды — команды сжимаются в памяти и распаковываются на первой стадии процессора.
  • Macro-operation Fusion — две или несколько простых команд считываются процессором и сливаются в одну более сложную команду.

На самом деле, в ARM уже используются обе эти стратегии, а в процессорах x86 применяется вторая, поэтому RISC-V не проделывает здесь каких-то новых трюков.

Однако тут есть тонкость: RISC-V получает из этих двух стратегий гораздо больше выгод по двум важным причинам:

  1. Сжатые команды были добавлены изначально. В других архитектурах, например, в ARM, об этом подумали позже, и прикрутили их довольно поспешным образом.
  2. Здесь оправдывает себя одержимость RISC малым количеством уникальных команд. Для добавления сжатых команд просто остаётся больше места.

Второй пункт требует некоторых пояснений. В архитектурах RISC команды обычно имеют ширину 32 бита. Эти биты нужно использовать для кодирования различной информации. Допустим, у нас есть такая команда (после точки с запятой идут комментарии):

ADD x1, x4, x8    ; x1 ← x4 + x8

Она складывает содержимое регистров x4 и x8, сохраняя результат в x1. Требуемое для кодирования этой команды количество битов зависит от количества имеющихся регистров. У RISC-V и ARM есть 32 регистра. Число 32 можно выразить 5 битами:

2⁵ = 32

Так как в команде нужно указать три разных регистра, то для кодирования операндов (входящих данных для операции сложения) требуется в сумме 15 бит (3 × 5).

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

Агрессивно стремясь к сохранению малого количества команд, RISC-V оставляет больше места для добавления битов, обозначающих, что мы используем сжатые команды. Если процессор видит, что в команде заданы определённые биты, то он понимает, что её нужно интерпретировать как сжатую.

Это означает, что вместо засовывания внутрь 32 бит одной команды мы можем уместить две команды по 16 бит шириной каждая. Естественно, не все команды RISC-V можно выразить в 16-битном формате. Поэтому подмножество 32-битных команд выбирается на основании их полезности и частоты использования. Если несжатые команды могут получать 3 операнда (входящих данных), то сжатые команды — только 2 операнда. То есть сжатая команда ADD будет выглядеть так:

C.ADD x4, x8     ; x4 ← x4 + x8

В ассемблерном коде RISC-V используется префикс C., сообщающий, что команду нужно преобразовать ассемблером в сжатую команду.

По сути, сжатые команды уменьшают количество операндов. Три регистра-операнда заняли бы 15 бит, оставив на указание операции всего 1 бит! Таким образом, при использовании двух операндов для указания опкода (выполняемой операции) у нас остаётся 6 бит.

На самом деле это близко к тому, как работает ассемблер x86, когда зарезервировано недостаточно битов для использования трёх регистров-операндов. Процессор x86 при этом тратит биты, чтобы позволить, например, команде ADD считывать входящие данные и из памяти, и из регистров.

Однако истинную выгоду мы получаем, объединив сжатие команд с Macro-operation fusion. Когда процессор получает 32-битное слово, содержащее две сжатые 16-битные команды, он может слить их в одну более сложную команду.

Звучит, как чушь — мы что, вернулись к тому, с чего начинали?

Нет, поскольку мы минуем необходимость заполнения спецификации ISA кучей сложных команд (то есть стратегии, которой придерживается ARM). Вместо этого мы, по сути, выражаем целое множество сложных команд косвенно, через различные сочетания простых команд.

В обычных условиях Macro-fusion вызвало бы проблему: хотя две команды заменяются одной, они всё равно занимают в два раза больше памяти. Однако при сжатии команд мы не занимаем никакого лишнего места. Мы пользуемся преимуществами обеих архитектур.

Давайте рассмотрим один из примеров, приведённых Эрин Шеперд. В своей критической статье о ISA RISC-V она показывает простую функцию на C. Чтобы было понятнее, я взял на себя смелость переписать её:

int get_index(int *array, int i) { 
    return array[i];
}

На x86 это скомпилируется в следующий ассемблерный код:

mov eax, [rdi+rsi*4]
ret

При вызове функции в языке программирования аргументы обычно передаются функции в регистре согласно установленному порядку, который зависит от используемого набора команд. На x86 первый аргумент помещается в регистр rdi, второй — в rsi. По стандарту возвращаемые значения должны помещаться в регистр eax.

Первая команда умножает содержимое rsi на 4. Он содержит переменную i. Почему умножает? Потому что array состоит из элементов integer, разделённых друг от друга 4 байтами. Следовательно, третий элемент массива находится в смещении 3 × 4 = 12 байт.

Далее мы прибавляем это к rdi, который содержит базовый адрес array. Это даёт нам окончательный адрес i-того элемента array. Мы считываем содержимое ячейки памяти по этому адресу и сохраняем его в eax: задача выполнена.

На ARM всё происходит похожим образом:

LDR r0, [r0, r1, lsl #2]
BX  lr                    ;return

Здесь мы не умножаем на 4, а сдвигаем регистр r1 на 2 бита влево, что эквивалентно умножению на 4. Вероятно, это более верное описание и того, что происходит на x86. Сомневаюсь, что можно умножать на что-либо, не являющееся кратным 2, поскольку умножение — это довольно сложная операция, а сдвиг малозатратен и прост.

Из моего описания x86 об остальном можно только догадываться. Теперь давайте перейдём к RISC-V, где начинается настоящее веселье! (точкой с запятой начинаются комментарии)

SLLI a1, a1, 2     ; a1 ← a1 << 2
ADD  a0, a0, a1    ; a0 ← a0 + a1
LW   a0, a0, 0     ; a0 ← [a0 + 0]
RET

На RISC-V регистры a0 и a1 являются просто псевдонимами x10 и x11. Именно в них помещаются первый и второй аргументы вызова функции. RET — это псевдокоманда (сокращение):

JALR x0, 0(ra)     ; sp ← 0 + ra
                   ; x0 ← sp + 4  ignoring result

JALR выполняет переход к адресу, хранящемуся в ra, который относится к адресу возврата. ra — это псевдоним x1.

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

Это действительно выглядит плохо. Именно поэтому Эрин Шеперд чрезвычайно критически отнеслась к проектировочным решениям, сделанным разработчиками RISC-V. Она пишет:

Упрощения RISC-V делают более простым декодер (т.е. фронтенд процессора), однако за это приходится расплачиваться бо́льшим количеством команд. Однако масштабирование ширины конвейера — это сложная задача, в то время как декодирование немного (или сильно) необычных команд хорошо изучено (основные сложности возникают, когда определение длины команды нетривиально — из-за своих бесконечных префиксов особо запущенным случаем является x86).

Однако благодаря сжатию команд и macro-op fusion можно изменить ситуацию к лучшему.

C.SLLI a1, 2      ; a1 ← a1 << 2
C.ADD  a0, a1     ; a0 ← a0 + a1
C.LW   a0, a0, 0  ; a0 ← [a0 + 0]
C.JR   ra

Теперь команды занимают ровно столько же места в памяти, что и пример для ARM.

Так, а теперь давайте выполним Macro-op fusion!

Одно из условий RISC-V для разрешения слияния операций в одну — это совпадение целевого регистра. Это условие выполняется для команд ADD и LW (load word, «загрузить слово»). Поэтому процессор превратит их в одну команду.

Если бы это условие выполнялось и для SLLI, то мы могли бы слить в одну все три команды. То есть процессор бы увидел нечто, напоминающее более сложную команду ARM:

LDR r0, [r0, r1, lsl #2]

Но почему мы не могли прописать эту сложную макро-операцию непосредственно в коде?

Потому что в ISA нет поддержки такой макро-операции! Вспомним, что у нас есть ограниченное количество битов. Тогда сделаем команды длиннее! Нет, это займёт слишком много памяти и быстрее переполнит драгоценный кэш процессора.

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

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

Macro-operation fusing немного переворачивает работу декодера вниз головой: вместо превращения одной команды в несколько микро-операций, мы берём много операций и превращаем их в одну микро-операцию.

То есть происходящее в современном процессоре может выглядеть довольно странно:

  1. Сначала он объединяет две команды в одну с помощью сжатия.
  2. Затем он разделяет их на две с помощью распаковки.
  3. Далее комбинирует их обратно в одну операцию при помощи macro-op fusion.

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

Ключевым аспектом перехода к микро-операциям является нужный уровень сложности:

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

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

Получаемые преимущества


Мы обсудили множество подробностей, поэтому сейчас вам, должно быть, трудно понять, в чём смысл всех этих трудов. Зачем нужны все эти сжатия и слияния? Похоже, что из-за них выполняется много лишней работы.

Во-первых, сжатие команд совершенно не походит на сжатие zip. Слово «сжатие» немного неверное, потому что мгновенное сжатие или распаковка команды выполняются абсолютно просто. На это не тратится времени.

То же самое относится к macro-operation fusion. Хотя этот процесс может казаться сложным, подобные системы уже используются в современных микропроцессорах. Поэтому затраты, которые добавляет вся эта сложность, уже были оплачены.

Однако в отличие от проектировщиков ARM, MIPS и x86, приступая к проектированию своего ISA, создатели RISC-V знали о сжатии команд и macro-ops fusion. Благодаря различным тестам с первым минимальным набором команд они сделали два важных открытия:

  1. Программы RISC-V обычно занимают примерно столько же или меньше места в памяти, чем любая другая процессорная архитектура. В том числе и x86, который должен эффективно использовать память, учитывая, что это ISA CISC.
  2. Ему требуется выполнять меньше микро-операций, чем другим ISA.

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

Это заставило коллектив разработчиков RISC-V удвоить усилия по реализации macro-operation fusion как фундаментальной стратегии RISC-V. В руководстве по RISC-V есть множество примечаний о том, с какими операциями можно выполнять слияние. Также в него внесены правки, упрощающие слияние команд, встречающихся в частых паттернах.

Благодаря малому ISA его проще изучать студентам. А это означает, что изучающему процессорные архитектуры студенту проще спроектировать собственный процессор, работающий на командах RISC-V. Стоит помнить, что и сжатие команд, и macro-op fusion использовать необязательно.

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

Macro-op fusion — это просто оптимизация. Она не меняет поведения в целом, а поэтому её необязательно реализовывать в собственном процессоре RISC-V.

Стратегия проектирования RISC-V


RISC-V взял всё, что мы знаем сегодня о современных процессорах, и использовал эти знания в проектировании процессоров ISA. Например, мы знаем, что:

  • Сегодня у процессорных ядер есть сложная система прогнозирования ветвления.
  • Процессорные ядра суперскалярны, то есть выполняют множество команд параллельно.
  • Для обеспечения суперскалярности используется выполнение команд с изменением очерёдности (Out-of-Order execution).
  • Они имеют конвейеры.

Это означает, что такие особенности, как поддерживаемое ARM условное выполнение, больше не требуется. Поддержка этой функции в ARM отъедает биты от формата команд. RISC-V может сэкономить эти биты.

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

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

Именно из-за этого RISC-V не имеет и регистров состояния, ведь они создают зависимости между командами. Чем более независима каждая команда, тем проще выполнять её параллельно с другой командой.

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



На правах рекламы


Наша компания предлагает серверы не только с CPU от Intel, но и серверы с процессорами AMD EPYC. Как и для других типов серверов, огромный выбор операционных систем для автоматической установки, есть возможность установить любую ОС с собственного образа. Попробуйте прямо сейчас!

VDSina.ru
Серверы в Москве и Амстердаме

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

    0
    А реальные цифры есть, в которых всю эту красоту можно оценить? А то постоянно слышно какой этот RISC-V замечательный, но хоть одну железку бы помучали прилюдно.

    Да и не процессором единым. Что с периферией? Привычные интерфейсы остаются коммерческими с оплатой за каждый проданный экземпляр. И насколько производительны контроллеры всяких PCIe по сравнению с x86-системами?

    Унифицирован ли процесс загрузки, или снова каждый производитель свой велосипед будет городить, как сейчас в мире ARM?
      +3
      Переферия — все там же и также: ей почти пофигу какая там ISA в процессоре.

      Тоже касается и загрузки — всякие uboot/uefi умеют в RISC-V — вполне себе стандарты (в зависимости от того что за девайс).
        0
        Переферия — все там же и также: ей почти пофигу какая там ISA в процессоре.

        В идеальном мире — да, а на деле реализации бывают очень разные. Очевидно, что встройка в процессор AMD или Intel будет отличаться от отдельного кристалла на плате с сабжем, вопрос, на сколько.

        Тоже касается и загрузки — всякие uboot/uefi умеют в RISC-V — вполне себе стандарты (в зависимости от того что за девайс).

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

        Что касается uefi, то он как бы и на некоторых ARM есть, но это такая редкость, что говорить не о чем. Тут вопрос больше, существует ли система волшебного пенделя, которая заставила бы производителей железа следовать единому стандарту, как это пока еще есть на потребительских x86.
          0
          У меня на столе прямо сейчас лежат два ARM-одноплатника разных производителей, которые используют uboot, но тем не менее они не способны даже начать грузить систему, если им поменять флешки.


          Если уж на то пошло, то и сборки UEFI тоже так же себя будут вести на любой архитектуре (исключением, может быть, будет payload для какого-нибудь coreboot). Другое дело, что у uboot нет стандартизированного интерфейса взаимодействия с ОС, поэтому они вынуждены имитировать UEFI.
        0
        Вот, например, из последнего: arstechnica.com/gadgets/2020/12/new-risc-v-cpu-claims-recordbreaking-performance-per-watt. Утверждают, что обходят все популярные десктопные процессоры по производительности на ватт, да и сама производительность уже не так плоха, хотя пока не было бенчмарков на реальных задачах.
          +2

          Не надо верить всему, что пишут в интернете: https://twitter.com/andreif7/status/1334862926218457090


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

          0
          У ARM есть спецификация EBBR года этак с 2017. То, что еще не все ее осилили — проблемы неосиливших.
            0

            "У ARM есть спецификация EBBR года этак с 2017. То, что еще не все ее осилили — проблемы неосиливших."
            Поясните пожалуйста!

          +5
          Спасибо за статью.

          Когда я сам по диогонали пробежался по принципам построения ISA RISC-V то обратил внимание по сути только на отсутствие регистра состояний — что показалось очень правильным для параллельного вычисления. Но оказалось, что две довольно важные вещи (сжатие и fusion) — как-то не прочувствовал.

          И собственно теперь понятно на чем зиждется заявления о меньших ватах/операцию для RISC-V: меньше микрокоманд для выполнения тех же действий — меньше и энергии потребуется.
            +2

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

              0

              Это VLIW. Попытки предпринималось неоднократно, но не взлетело. Слишком сложный компилятор, низкая плотность кода (больше обращений к памяти), плюс, процессор при реордеринге и спекулятивном выполнении имеет рантайм-информацию, а компилятор -нет.

                0
                Взлетело. www.mcst.ru
                  0
                  Еще очень рано ИМХО судить взлетело ли оно или нет.

                  Собственно, пока это все гос заказ — вообще трудно говорить о «взлете» — даже если оно не летит, тему могут тянуть бюджетные деньгами очень долго.

                  ЗЫ Хотя не могу не согласиться что оно все-таки кое как летает, судя по отзывам и обзорам, хотя и не очень высоко летает.
                    +2
                    На свободном рынке нет, негосударственных заказов нет, даже в апстриме того же линукса нет. Что-то это мало похоже на «взлетело».
                      +2
                      Насколько я знаю, они даже документацию на систему команд зажучили и никому не показывают. С таким подходом никогда не взлетит.
                0
                RISC-V конечно интересный проект, но говорить о какой-то гениальности я бы не стал.
                Всегда в выигрыше тот, кто посмотрит на сделанные ранее архитектуры, сделает хороший системный анализ, выберет сильные стороны, отбросит слабые. Но другие «не гениальные » архитектуры уже приносят пользу, а у этой еще все впереди. Также не пойму о какой простоте системы команд пишет автор. Возможно статья писалась когда была доступна только версия команд R32I. Нескончаемым потоком пишутся все новые расширения для этой архитектуры :) Какой бы ни была эта архитектура, лучшие процессоры RISC-V сделают те же разработчики которые сейчас делают лучшие x86, ARM,MIPS и т.д. Но несомненная польза RISC-V в том, что попрактиковаться в проектировании этой архитектуры процессора может каждый. И ничего ему за это не будет :)
                  +1

                  Хоть кто-нибудь смог реально сделать fusion в железе RISC-V? Пока нет такого железа, рассказы про то, что это преимущество, ничего не стоят.

                    +3
                    То, что в ARM есть пост-инкрементная адресация, в Р5 будет две команды. Автор объясняет, что пост-инкрементная адресация это очень сложно и лучше две раздельные команды. Вы их можете скомпрессировать(если получится), но внутри процессора вы можете эти две простые команды превратить в одну ARM-команду, чтобы выполнить её за один такт. Ведь это же проще чем декодировать одну сложную команду. Но вам нужно позаботится о том, чтобы компилятор вам эти команды расположил рядом, а лучше вообще в одном слове. Если не разместит, придется вам делать черти какой буфер команд и искать в нем подругу для склейки. Это если вы хотите сделать крутой процессор. Если простой, то два такта и отдыхайте. Можно конечно просто запускать 2 команды за такт. Так вроде даже проще чем клеить две команды в одну. Но 2 команды за такт это уже два конвейера, многопортовый регистровый файл и т.д.
                      0
                      Поторопился немного :) Но уже не исправить. fusion это про Ерему, а я про Фому. Но Фома тоже не подарок.
                        +1

                        Post increment как раз эффективней пилить на 2 микрооперации. В этом случае на out-of-order superscalar инкремент не будет дожидаться окончания лоада. А лоад может зависнуть на много сотен тактов в случае cache miss. А вот индексация массива по регистру лучше делается одной микроопераций: лоад всё равно нельзя запустить до того, как будет вычислен адрес. А адресация (base + offset) уже есть, то есть в address generation unit есть сумматор. В железе не слишком сложно завести туда данные из регистра вместо immediate value из опкода. В RISC-V эту задачу должен решить fusion, но пока не видно железа, которое это умеет. На моей прошлой работе такое пытались сделать (не для RISC-V, для собственной архитектуры), но это не заводились на частотах выше 350 МГц

                          0
                          спасибо. Беру на заметку.До out-of-order я еще не дошел :)
                    –4

                    .

                      0
                      Можно, пожалуйста, объяснить, как именно ISA RISC-V способствует уменьшению количества выполняемых микроопераций? Macro-ops fusion — это, конечно, умно, но он позволяет превратить lookup массива аж в 2 микрооперации, тогда как в тех же ARM/x86 они без какого-либо напряга могут быть сделаны одной, были бы соответствующие исполнительные устройства.
                        0
                        Именно из-за этого RISV-C не имеет и регистров состояния, ведь они создают зависимости между командами.

                        Я бы скзаал, что склейка комманд это как раз и есть зависимость. Фактически это проброс имён регистров в следующие комманды (если обе комманды за 1 такт, а не просто экономим на передаче операндов, то это вообще CISCовый треш и разбазаривание транзисторов, которые можно было пустить ещё на 1 конвеер), то же самое можно было бы реализовать, если, например, кешировать последние три имени использововашихся регистров и в последующих коммандах просто битиком отмечать, что операнды берём из кеша имён регистров.
                        Единственное, чего они действительно добились, это — опциональность такого подхода и это же огромный минус: может работать, а может не работать, может склеиться, а может не склеиться, программист тоже мог учестЬ, а мог не учесть. Я бы сказал, что очень спорное решение, можно было придумать что-нибудь более явное и простое, типа кеша.
                          0

                          ADD a0, a0, a1; a0 ← a0 + a1
                          C.LW a0, a0, 0; a0 ← [a0 + 0]


                          Почему нельзя
                          LW a0, a0, a1
                          ?

                            +2

                            Потому что в RISC-V нельзя закодировать такую инструкцию

                              0
                              Без сжатия.
                              LW a0, a0, a1; a0 < — [a0 + a1]
                              Или смещение должно быть не в регистре?
                                +1

                                В RISC-V смещение должно быть закодировано числом в инструкции. Регистр нельзя. Разработчики считают, что железо должно уметь склеивать две инструкции в одну в конвейере. Но такого железа пока не видно.

                            +2
                            Ощущение, что нас где-то обманывают…
                            Сия фича была предложена в архитектуру RISC-V только в 2016, и, на сколько я знаю, нигде ещё не была реализована и не понятна когда и где будет. Так что вся эта хвалебная ода, это сравнение некоторого теоретического процессора с неизвестными характеристиками с реальными и работающими.
                              0
                              Когда только появилась первая версия R32I, была шутка про отсутствие бита переноса. Посмотрел как сейчас будет сложение 2-х 64-бит чисел в наборе R32I.
                              add a3,a5,a1
                              mv a0,a3
                              sltu a0,a0,a5
                              add a4,a6,a2
                              add a5,a0,a4
                              Интересно, fusion здесь тоже применяют?
                                0

                                В MIPS примерно то же самое (https://stackoverflow.com/questions/1281806/adding-two-64-bit-numbers-in-assembly). Это наводит на мысль о том, что RISC-V instruction set по большей части содрали с MIPS, не проводя какого-то анализа других архитектур.

                                  0
                                  Зачем сдирать с MIPS, если RISC-V проектировали авторы MIPS? Они же авторы самой идеи RISC архитектуры. Ищите David Patterson & John Hennessy.

                                  Про отсутствие анализа других архитектур, мягко говоря вздор. Даже на русский есть переводы анализа архитектур: Паттерсон «Компьютерная архитектура. Количественный подход. Руководство».
                                    +1

                                    Это, простите, не анализ а научно-популярная литература для широкого круга интересующихся. Написано, правда, хорошо, этого не отнять.
                                    Нормальный анализ делается с применением потактовых симуляторов, и приводит к тому, что в архитектуре появляются инструкции, которые в RISC-V не представлены. В понимании авторов RISC-V, это должен обрабатывать instruction fusion. Но покажите мне железо, в котором это реализовано.

                                      +1

                                      Это самый крутой из доступных без NDA учебник уровня старших курсов магистратуры вообще-то. Т.е. всё что круче — уже статьи в peer-reviewed журналах если повезёт, а если не повезёт (что скорее всего и будет) — патенты и внутренние публикации.


                                      Монографий круче нет.

                                    0
                                    Спасибо, еще раз. По ссылке очень интересное замечание по поводу расстановки команд, чтобы процессор мог их выполнять параллельно если он может это делать. Получается, что если расставил «неудобно» для процессора, то он(процессор) тормознет :) Тогда в выигрыше те, у кого свой компилятор который удобнее расставит команды для «своего» процессора. По крайней мере процессор может быть проще.
                                      +1

                                      В out-of-order superscalar это не настолько важно: в процессоре будет буфур декорированных инструкций, из которого процессор будет брать готовые для исполнения команды. И по большому счёту не очень важно, в каком порядке они идут в коде программы. Вот в in-order superscalar важнее, чтобы компилятор правильно расставил инструкции. Для этого в компиляторах планировщики пишут. В out-of-order компилятор тоже более-менее оптимально пытается расставить инструкции, но это нужно скорее для того, чтобы декодирование не тормозило.

                                  0
                                  У ARMv8 уже нет встроенных сдвигов
                                    0

                                    Есть. Но сильно ограничены: только LSL на размер данных в LDR/STR.

                                    0
                                    «Одно из условий RISC-V для разрешения слияния операций в одну — это совпадение целевого регистра. Это условие выполняется для команд ADD и LW (load word, «загрузить слово»). Поэтому процессор превратит их в одну команду.»
                                    А почему не эти?
                                    C.SLLI a1, 2; a1 ← a1 << 2
                                    C.ADD a0, a1; a0 ← a0 + a1
                                      +1
                                      По теории автора — не совпадает целевой регистр (a1 и a0). Придется в одном такте писать в регистры сразу два результата. Видимо, по их теории, так делать нельзя.
                                        0
                                        То есть запись от первой команды можно игнорировать, просто передав ее результат bypаss во вторую. Тогда понятно.

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое