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

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

Краткость сестра таланта

Кр.-сес.тал. тогда уж ;)

Интересно. Получается, что в наше время х86 это тупик в своем нынешнем виде?

Да, x86 ещё 20 лет назад был помойкой из легаси. Сейчас все ещё хуже.

Для разработчиков это значит, что написание и оптимизация кода ARM станет проще.

Вот на каком основании этот вывод? Всё только усложняется. Компиляторы станут сложнее, отладка сложнее, баги станут интереснее. Гиды по написанию оптимального кода тоше. Более того обычные способы программирования не подходят, а писать в виде вычислительных ядер и пайплайнов код не всегда удобно. Просто большинство продолжат писать как писали на swift, kotlin и java или даже javascript и ждать всяких готовых SDK которые используют новые возможности процессоров. В результате подобных SDK станет еще больше opengl, vulcan, opencl, openvx, openxr…

Понятное дело, для программистов на ЯВУ вообще ничего не изменится (для них и между x86 и ARM большой разницы нет), а вот для тех, кто пишет производительный низкоуровневый код это в теории даёт возможность одну и ту же оптимизацию применять как для смартфонов, так и для суперкомпьютеров без изменений в коде.


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

Компиляторы станут сложнее

Сегодня в компиляции под x86, например, есть параллельные друг другу генерации под SSE, AVX (то же но с трёхадресными в основе командами), AVX2 (256 бит), AVX512 (512 бит). Под SVE один универсальный подход на всё — сколько позволяет процессор обработать за раз, столько и будет.


Гиды по написанию оптимального кода тоше.

Аналогично, не будет сверхтонких различий типа "вот это неэффективно разгонять до 512 бит".


отладка сложнее, баги станут интереснее

Почему?


Более того обычные способы программирования не подходят, а писать в виде вычислительных ядер и пайплайнов код не всегда удобно.

Для тех, кому не нужна / не подходит векторизация, ничего не меняется.

эволюция. сначала и динозавры были маленькими а потом росли и росли росли и росли пока не вымерли. и x86 был маленьким скромненьким процессор но начал расти расти пока не превратился в неповоротливого монстра. как и arm был маленьким скромным процессором но начал расти и расти, расширять, добавляться новые инструкции и настанет тот день когда и он станет большим и неповоротливым монстром.

Либо станет большой и сильной годзиллой ;)

Это не так работает. Проблема x86 в том, что длина инструкций нефиксированная.

В ARM уже масса проблем от впихивания в фиксированную длину. У того же SVE где-то допустимы 16 предикатных регистров, а где-то 8. И даже в базовом наборе команд пачка неровностей типа "тут можно 12 бит смещения, а тут только 9". Если бы часть команд была 32 бита, а часть 32+32, это бы не ухудшило существенно логику ARM. (А тем более в варианте, где первая и не-первая часть заведомо по-разному закодированы — как в стиле utf-8 — были и такие предложения.) Разумная нефиксированность могла бы вполне помочь в таком стиле, но ARMовцы этого не хотят.
Когда длины инструкций не хватает, начинаются разные странные выбрыки. Посмотрите на System/Z (длина инструкции ограничена 6 байтами и почти все значения уже использованы) и монстры типа PFPO: код операции складывается в регистр 0. Очевидно, это убивает возможности по предсказанию действия, распределения по АЛУ в зависимости от операции и т.п.
Что дальше — передача данных и команд в сопроцессоры, как в MIPS и ранних ARM?

А тем более в варианте, где первая и не-первая часть заведомо по-разному закодированы — как в стиле utf-8 — были и такие предложения.

Хм, ну вот это, возможно, и норм вариант. Но x86 в любом случае мимо.
Надеюсь, что это не так, есть что-то хорошее в обратной совместимости.
z80 большая часть перетекла в 86 появился костыль сегментные регистры
это как если мы делали одноэтажные здания (8-бит 64кб), а нас попросили сделать многоэтажку (адресацию 1мб), и мы сделали много одно-этажек, и поставили друг на дружку
Добавилась порция команд 186 и 286
32 битный 386 и тут почему-то мы в 32битном режиме мы оставили костыль из сегментных регистров.
Много всяких дополнений команд типо MMX.
Великолепный 64 битный режим AMD64 тут отказываются от сегментных регистров (видно не intel, а amd)
Столько транзисторов тратится на это богатство, и всё ещё на i5 работает бесполезная инструкция z80 AAA.

Сколько сомнительной вода, а плюс существу лишь пару абзацев не менее сомнительного качества

Очень много пафоса. Хорошее образное сравнение SVE2 приведено в англоязычной ссылке статьи. Гоночный автомобиль и фура. Вот кому нужна фура, тот будет использовать ядра с SVE. ARM старается «пометить» все углы. Не успеешь — другие описают.

Интересно, а в чем преимущество ARM перед Power в этом сегменте?
IBM дает ISA забесплатно, плюс патенты. И у них большой опыт в использовании архитектуры для серверов и суперкомпьютеров.

В каком сегменте? ARMv9 будет как в телефонах или серверах, так и в автомобилях и т.д.
Power — мёртвая архитектура де факто. Она осталась только в больших системах и у энтузиастов. Кто будет поддерживать софт под неё?
Чтобы запустить и отладить код, ARM комп можно купить за «копейки».
В сегменте серверов.
Чтобы запустить и отладить код, ARM комп можно купить за «копейки».

Последний раз, когда я проверял, компиляция проекта размером с GCC на ARM-компе «за копейки» занимала раз в 10-20 дольше, чем на x86-компе за те же деньги.

Ну а теперь с M‐процессорами всё иначе

Векторы это конечно хорошо, а как же операции непосредственно над матрицами? С развитием этих ваших нейросетей как раз это будет более актуально, чтобы отдельные «сопроцессоры» к «цпу» не городить. В ту же тему – многоядерность, более удобные низкоуровневые команды для параллельных вычислений, наверное в эту сторону будет тоже делаться большой упор.
И есть ли принципиальная разница между архитектурами в плане добавления новых команд? Что мешало в х86 добавить те же красивые команды с масками, вместо того, чтобы городить отдельный набор команд под каждый размер вектора? Наверное даже сейчас можно это добавить, ещё пара десятков новых инструкций сильно картину не испортит )
Вообще, с позиции дилетанта, представилось страшное: процессор архитектуры ARMx86, поддерживающий оба набора инструкций, вот бы жизнь началась тогда радостная!
Векторы это конечно хорошо, а как же операции непосредственно над матрицами?

Они там уже есть.
community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-architecture-developments-armv8-6-a
GEMM — General Matrix Multiply
У Apple есть собственное нестандартное расширение AMX.

Что мешало в х86 добавить те же красивые команды с масками

Команды с масками есть в AVX-512.
Переменную длину вектора не добавили потому что с радостью вам продадут новый AVX-1024, не совместимый с AVX-512.

И есть ли принципиальная разница между архитектурами в плане добавления новых команд?

У ARM есть место для новых инструкций, а в х86 не особо и из-за префиксов там уже средняя длина инструкции в FP коде — 6 байт.

x86 — одеяло сшитое из заплаток разных эпох.
Добавили через VEX-префикс 3-операндные инструкции, но только для SIMD.
У ARM есть место для новых инструкций, а в х86 не особо

Всё наоборот. Сколько того места в фиксированных 32 битах у ARM и сколько из них можно израсходовать, не опасаясь за следующий круг расширений? В текущем пространстве уже тесно и экономия началась с самого начала (почему в LDR в разных вариантах смещение или 19, или 9 бит? а почему нет LDR с вычислением адреса rs1+rs2 * scale+offset, а есть только rs1 + offset и rs1 + rs2 * scale?), и продолжается сейчас (SVE — почему где-то 16 предикатных регистров, а где-то только 8?)


Переменная длина тем и хороша, что позволяет неограниченное расширение.
У x86 проблема не в самой переменной длине, а в том, что она сделана крайне коряво — сначала надо декодировать несколько первых байт, чтобы добраться до тех, что могут уточнять длину (mod-reg-r/m и SIB); это, конечно, параллелится, но очень дорого. То, что было хорошим решением в 1978, стало тяготить уже в 1990. Даже переход на 16-битные чанки с частичным выносом признака длины вперёд уже мог бы в разы удешевить декодинг.


Есть как минимум два альтернативных эффективных подхода — 1) префикс длины идёт перед всем остальным (System/Z, RISC-V) и 2) неперекающиеся множества первых и не-первых слов (utf-8, не знаю, есть ли в реальных ISA — аналогом была бы, например, фиксированная группа старших бит в слове). Оба на порядки удешевляют декодинг и в то же время не запрещают расширение набора инструкций.


Но и сейчас в x86 можно дорисовывать что угодно, платя за это всего лишь утолщением кода; а в ARM когда-нибудь просто упрутся в физическую невозможность… и тогда всё равно будет расширение, но так же коряво, как в x86. Привет от Роберта Фано.


x86 — одеяло сшитое из заплаток разных эпох.
Добавили через VEX-префикс 3-операндные инструкции, но только для SIMD.

Да. Но ведь смогли добавить. Смогли бы и для всех базовых команд, но решили, что того не стоит. Для сравнения: в System/Z тоже добавляли трёхадресные инструкции, но только то, что сочли самым критичным.

Есть как минимум два альтернативных эффективных подхода — 1) префикс длины идёт перед всем остальным (System/Z, RISC-V)

..., Thumb.

Если ARM отказались от того, что у них уже было готово и уже работало, значит, были на то веские причины.
(Насколько я знаю — они взяли огромную базу «реального кода», пробовали для него разные варианты кодировок, и пришли к выводу, что «32 бита хватит любому».)

Вообще, очень интересно соперничество «слепой эволюции» и «разумного замысла» в этой сфере; подозреваю, что его итоги будут иметь значение не только в IT :)
..., Thumb.

Хм, спасибо, буду знать.


Если ARM отказались от того, что у них уже было готово и уже работало, значит, были на то веские причины.

Ну, вполне возможно, они зарезервировали часть кодов для расширения, но держат это в секрете. Также можно для не-первых слов использовать пространства hint-инструкций и просто NOPов всех видов (а на трёхадресной архитектуре любое add wzr, ws1, ws2 это NOP, то есть, их миллионы).


Вообще, очень интересно соперничество «слепой эволюции» и «разумного замысла» в этой сфере; подозреваю, что его итоги будут иметь значение не только в IT :)

А куда ещё? Ну и эволюция x86 не совсем таки слепая :)

В текущем пространстве уже тесно и экономия началась с самого начала

Разумеется. А как иначе? Пространство нужно грамотно распределять изначально.

почему нет LDR с вычислением адреса rs1+rs2 * scale+offset
А с чего взяли что он должен быть? Такой адресации в ARM никогда не было и не будет, потому что это совсем не RISC подход.
В ARM изначально ALU выполнял обязанности AGU, поэтому адресация там симметрична и сдвигатель может выполнять любую операцию, которая поддерживается для арифметических операций.
Рекомендую посмотреть как устроен ARM1.
Кстати сейчас в процессорах Apple наоборот, AGU работают как дополнительные ALU.

В наше время суперскалярных процессоров упомянутая вами адресация не то что бессмысленная, а вредная, потому что усложняет AGU и замедляет время такта без какого либо преимущества.

Зачем делать 2 сложения, когда можно сделать так (за пределами цикла):
rs1+rs2 * scale+offset => (rs1+offset)+rs2 * scale

Собственно некоторые утверждают что в RISC следует ограничить количество операндов 2+1 (2 вход, 1 выход). Но это убирает целый класс полезных инструкций (fma) и удобную адресацию.
В любом случае base + index * scale и так закрывает любую разумную потребность.

Но и сейчас в x86 можно дорисовывать что угодно, платя за это всего лишь утолщением кода; а в ARM когда-нибудь просто упрутся в физическую невозможность… и тогда всё равно будет расширение, но так же коряво, как в x86.

В ARMv7 столкнулись. Появился ARMv8. Problem solved.
Программу x86-64 вы всё равно не запустите на 386. Нет никакого смысла жить в рамках старых ограничений.

Сделать декодер на несколько наборов инструкций — не проблема. Сейчас есть и ARMv7, ARMv8, T32, Thumb.

Впрочем, один костыль для SVE всё таки есть:
developer.arm.com/documentation/ddi0596/2020-12/SVE-Instructions/MOVPRFX--unpredicated---Move-prefix--unpredicated--
А с чего взяли что он должен быть? Такой адресации в ARM никогда не было и не будет, потому что это совсем не RISC подход.

Смотря с какой точки зрения. Если считать, что RISC это "как можно больше команд, суть которых выполняется за 1 такт (ну максимум 2)", то ничего не мешает добавить такую адресацию. Это же не PDP-11 "сходим в память, получим адрес, а теперь ещё раз по новому адресу сходим и там будет значение, а теперь ещё и после операции запишем туда результат".


ARM как раз показывает какими-нибудь BFM, MADD или доступом к памяти с пост-индексной модификацией, как именно надо понимать "простые команды" и "простой набор команд".


Зачем делать 2 сложения, когда можно сделать так (за пределами цикла):
В любом случае base + index * scale и так закрывает любую разумную потребность.

Ну вот именно что "за пределами цикла". Пусть есть что-то типа


for (i = 0; i < n; ++i) {
  foo[i].buka = foo[i].zuka * foo[i].karkuka;
}

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


В наше время суперскалярных процессоров упомянутая вами адресация не то что бессмысленная, а вредная, потому что усложняет AGU и замедляет время такта без какого либо преимущества.

Насчёт "замедляет время такта", по-моему, ни у кого у нас нет точных данных. И это никак не фатально с учётом всяких умножений-делений. Но ok...


В ARMv7 столкнулись. Появился ARMv8. Problem solved.

Это могло пройти только один раз за счёт неизбежного изменения всего при изменении адресации 32->64 бита. Честь им и хвала, что это сделали (в отличие от x86, где эту возможность профукали), но следующий такой переход… к 128 битам точно не будет ещё лет 50, и что, ждать квантово-оптических фитоэлектронных процессоров или ещё какой-то принципиально меняющей всё реформы?


Сделать декодер на несколько наборов инструкций — не проблема. Сейчас есть и ARMv7, ARMv8, T32, Thumb.

А вот khim@ заявлял на похожую тему, что ARMовцев уже тяготит необходимость держать рядом A32 декодеры.


Программу x86-64 вы всё равно не запустите на 386. Нет никакого смысла жить в рамках старых ограничений.

Добавятся новые. Сейчас уже есть легаси в x86-64 в виде процессоров без AVX. В ARMv8.0 — без умения всяких CAS. Скоро легаси будет отсутствие SVE. Дальше что?


Разумеется. А как иначе? Пространство нужно грамотно распределять изначально.

Это если у вас хрустальный шар есть, причём работающий. У Intel его явно не было, иначе бы не было метания каждые три года в новую сторону… и у ARM нет, несмотря на несколько больший разум разработчиков.


Впрочем, один костыль для SVE всё таки есть:

"Ну вот, началось" ©

Если считать, что RISC это «как можно больше команд, суть которых выполняется за 1 такт (ну максимум 2)», то ничего не мешает добавить такую адресацию.

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

ARM как раз показывает какими-нибудь BFM, MADD или доступом к памяти с пост-индексной модификацией, как именно надо понимать «простые команды» и «простой набор команд».

Именно что простой. FMA это один блок с тремя инпутами, который делает fused — операцию.
Если вы посмотрите на организацию ARM1, поймёте, что такие вещи как op + shift, пре/пост инкремент делаются очень просто. На OoO процессоре они делаются сложнее, но там гораздо выше планка по сложности.

Будете держать 3 регистра базы со смещениями?

Зачем? В таком цикле вообще не нужна никакая адресация кроме base + imm offset.
gcc.godbolt.org/z/qhn8ha95r

И это никак не фатально с учётом всяких умножений-делений.

Чтение данных из памяти концептуально сложнее чем умножение/деление.

Это могло пройти только один раз за счёт неизбежного изменения всего при изменении адресации 32->64 бита.

Кто сказал? Это просто был удобный момент. Но уж не единственный.
Условный ARMv10 спокойно может поменять кодировку.
Старые программы как работали, так и будут работать.

то ARMовцев уже тяготит необходимость держать рядом A32 декодеры.

На декодеры плевать вообще. В последних A77-A78 есть кэш микроопераций.
У ARMv7 есть несколько особенностей, которые мешают — прямой доступ к PC, LDM/STM, регистровые банки, предикация в каждой инструкции и т.п.

Скоро легаси будет отсутствие SVE. Дальше что?

Правильно. На новые чипы будут собирать с SVE2 и TM в базе.
Такие программы не будут работать на старых ARMv8 процессорах.
Fat binary никуда не уйдёт.

Зачем? В таком цикле вообще не нужна никакая адресация кроме base + imm offset. gcc.godbolt.org/z/qhn8ha95r

И в amd64 хорошо видно как раз: "lea rdx, [rdi+12+rdx*4]".
А теперь чуть исправим: https://gcc.godbolt.org/z/8razchEGM
Ой, откуда это у нас madd в цикле? "Хто ета зделаль?"


Именно что простой. FMA это один блок с тремя инпутами, который делает fused — операцию.

Ну вот fused из двух сложений проще, чем из сложения с умножением. Проблема таки только в выходе за пределы "2 входа — 1 выход".


Чтение данных из памяти концептуально сложнее чем умножение/деление.

Тем более.


Кто сказал? Это просто был удобный момент. Но уж не единственный.
Условный ARMv10 спокойно может поменять кодировку.
Старые программы как работали, так и будут работать.

И как будет переключаться процессор между кодировками на границах переходов туда-обратно, например, для библиотеки собранной по-старому? Будете делать санки со сменой чего-то в PSTATE?
А легаси оно такое, оно не согласится на вариант "собираем всё под новый процессор".


Fat binary никуда не уйдёт.

Для этого надо заранее собрать библиотеки к тому fat binary под ещё не разработанную ISA. Печалька...


Собственно, на x86 всё это уже проходили. И не только на нём (вон про SPARC говорят). Программ, от которых тупо потеряны исходники, но надо как-то запускать — вагон и тележка. Но даже если не потеряны, совместимость давит. ARMовцы cчастливы, пока не почувствовали это на себе — но с выходом хотя бы на лаптопы это ударит в полный рост.

И в amd64 хорошо видно как раз: «lea rdx, [rdi+12+rdx*4]».

Видно что? Последовательность LEA это просто умножение на 12 + база, чтобы найти конец массива. Выполняется за циклом.
Она не используется для адресации.
=> адресация с доп. оффсетом не нужна

Из-за отсутствия трёхоперандных инструкций, х86 компиляторы вынуждены использовать LEA для таких вещей. А ведь бывает и так:
software.intel.com/content/www/us/en/develop/documentation/vtune-help/top/reference/cpu-metrics-reference/slow-lea-stalls.html

Some LEA instructions, most notably three-operand LEA instructions, have increased latency and reduced dispatch port choices compared to other LEAs.

try to avoid their use.


Ой, откуда это у нас madd в цикле? «Хто ета зделаль?»

В таком цикле (без зависимостей между итерациями) один madd дешевле чем его эквивалент через shift+add.
lea rdx, [rdx+rdx*2]
lea rdx, [rdi+rdx*4]

При желании на ARM base+index*12 считается аналогично
add tmp,idx,idx LSL #2
add tmp,base,tmp LSL #4

На ARM цикл 7 инструкций, на х86 — 9.
При прочих равных х86 нужно выполнить на 28% больше инструкций.
Опять же внутри цикла не используется адресация с доп. оффсетом
=> адресация с доп. оффсетом не нужна, что вы прекрасно доказали.
Браво!

И как будет переключаться процессор между кодировками на границах переходов туда-обратно, например, для библиотеки собранной по-старому?

ARM<>THUMB переключался. Впрочем сейчас v7/v8 только через прерывание.
Зависимость от старых либ это временная проблема на время перехода.

Для этого надо заранее собрать библиотеки к тому fat binary под ещё не разработанную ISA. Печалька…

Нет, нужно собирать бинарь под текущую архитектуру и старую, которую ещё не задепрекейтили.

но с выходом хотя бы на лаптопы это ударит в полный рост.

У меня на ARM ноуте запускаются как ARMv7, ARMv8, так и x86 код =)
Опс…
add tmp,idx,idx LSL #1
add tmp,base,tmp LSL #2
Конечно же.

У меня на ARM ноуте запускаются как ARMv7, ARMv8, так и x86 код =)

Вот. Можно вообще не париться и юзать вместо декодеров совместимости статическую трансляцию кода ARMv7/v8/v9 → ARMv10

Кто-то упоминал, что у Transmeta или Cyrix торчали наружу RISC-потроха в виде Alternate Instruction Set. Так что, в целом, ничего не мешает.


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

Проблемы не в технологии: Project Denver was originally intended to support both ARM and x86 code using code morphing technology from Transmeta, but was changed to the ARMv8-A 64-bit instruction set because Nvidia could not obtain a license to Intel's patents.[19]

Так есть минимум две компании, обладающие нужными патентами.

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

Исторически так сложилось, что не x86 не arm их основные ядра не умеют делать вычисления с плавающей точкой.
Например 1 + 2 может вычислить основное ядро, 1.5 + 3.5 уже не может, оно конечно может разложить эти числа, на до запятой и после, но эти вычисления будут не эффективны.
Пишу по памяти, начиная толи с 386 толи 486 у процессоров появился «математический сопроцессор», он то и позволил эффективно оперировать с числами с плавающей точкой, процессор просто загружал в него два числа и команду и получал готовый ответ.
Но поначалу он был как внешнее устройство и общение с ним шло через внешнюю шину. Хотя начиная с 486dx они уже изготавливались на одном кристалле.
И до появления пентиумов всех это устраивало, обратная совместимость и тд.
Но в пентиумах появились множители, ядро процессора его команды и регистры стали работать на частоте превосходящую частоту шины (будь то памяти или внешнюю). И работа с математическим сопроцессором стала тормозной.
И тогда интел придумала набор инструкций для прямого общения ядра и сопроцессора и назвала его MMX. Маркетологи обозвали его мультимедия экстеншн
Все остальные SSE SSE2 и тд, это матемаческий сопроцессор рос и развивался и для новых его фич требовались новые интерфейсы управления.
Все просто по сути.

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

Там, где есть возможности встраивать SIMD, сопроцессоры для плавающей точки давно не используются, всё в основном блоке АЛУ. Вы вспомнили что-то по состоянию на 1980-е. С тех пор изменилось "чуть более, чем всё".


Исторически так сложилось, что не x86 не arm их основные ядра не умеют делать вычисления с плавающей точкой.

Эта историчность неактуальна ни для x86 начиная с PPro, ни для ARMv8 и последующих.

на сколько я вижу размер avx регистров удваивается, я не эксперт в этой области, но возникает: вопрос можно ли декодер обучить трактовать сложение двух 256 векторов как один 512. если да, то как бы и нет проблемы. маски и прочее есть в avx

В языках шейдеров для GPU есть уже такая тема с выбором компонент вектора. Называется swizling.
Хорошо бы расшарить простаивающие части АЛУ. Сложение, умножение, сдвиги, запись и т.д. схематично это разные цепи.
Можно было бы сэкономить на транзисторах, например 8 ядер, 6 алу.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий