LINUX.ORG.RU

Понимание широкой команды, VLIW

 ,


4

2

Лорчик, у меня тут вопрос возник, чисто теоретический.

Есть VLIW, архитектура e2k. Если посмотреть ассемблерный код, то команда там будет в фигурных скобках. Это и есть одна широкая команда.

Пример:

{
  nop 2
  istofd,3    %g17, %g18
}
{
  nop 7
  sdivs,5     %g17, %g16, %g16
}

В документации сказано, что одна такая широкая команда выполняется процессором за 1 такт. Справедливости ради, нужно заметить, что здесь ни слова про ядра. Просто сказано, что за один такт.

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

Поскольку e2k не содержит жуткого блока предсказаний, как на обычном х86_64 и не умеет распаралеливать команды сам. За него это делает компилятор. Вот для этого и нужна эта широкая команда - компилятор распаралелил, перетасовал команды и сказал как их надо выполнить.

А теперь вот вопрсик в связи с этим. Получается, что прогу для e2k придется пересобирать для разных e2k процессоров с разным числом ядер?

Допустим прога собрана для Эльбрус 8С, у которого 8 ядер. Значит в фигурных скобках будет много команд. Т.е. широкая команда будет ну очень широкой, широчайшей прям! А запустится ли этот получившийся бинарник, скажем на 4С, у которого только 4 ядра? А на 1С? В смысле без пересборки.

★★★★★

ответ с дивана

суть-то широкой команды именно в том, чтобы распределить мелкие команды внутри этой широкой между ядрами процессора

Не думаю что суть в этом. Не обязательно между ядрами распараллеливание будет.
Может между разными 'блоками'(ну там типа АЛУ, SSE и т.д.) процессора.

Bad_ptr ★★★★★
()

чтобы распределить мелкие команды внутри этой широкой между ядрами процессора

Нет, суть в том, чтобы распределить операции по модулям ядра. Это же суперскаляр, там несколько АЛУ.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Окей, но на вопрос, по-моему, это не отвечает. Или внутри одного ядра всегда фиксированное число АПУ, что на 1С, что на 8С?

hibou ★★★★★
() автор топика
Ответ на: комментарий от hibou

Это, кстати, рождает больше вопросов, чем ответов. Получается, изменив число АПУ в будущем внутри одного ядра, они весь софт превратят в тыкву.

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

hibou ★★★★★
() автор топика
Ответ на: комментарий от hibou

внутри одного ядра всегда фиксированное число АПУ, что на 1С, что на 8С?

Разное. Но как на обычном х86_64 и не умеет распаралеливать команды сам - неверно. Обычный x86 хоть и имеет распараллеливатель, но он тупой. Компилятор всё равно должен тасовать команды под конкретный проц.

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

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 2)
Ответ на: комментарий от hibou

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

Ещё раз - по ядрам их не делят. Но да, есть такая проблема, что если нельзя загрузить все модули (зависимые вычисления и т.п.), то команда получается на 90% «пустая», плотность кода очень страдает.

Короче, получается огромная ответственность лежит на компиляторе

Именно. Я бы даже сказал, что нужно обязательно компилять с предварительным профилированием, иначе компилятору будет трудно на лету предсказывать переходы и т.п. статически. Ещё для jit тоже вкусные возможности открываются в теории.

no-such-file ★★★★★
()

Как бы суть-то широкой команды именно в том, чтобы распределить мелкие команды внутри этой широкой между ядрами процессора

В смысле? Пакет команд vliw - это про задействование разных исполнительных блоков внутри одного ядра.

devl547 ★★★★★
()
Ответ на: комментарий от devl547

Это мы поняли, выше объяснили. Осталось понять число исполнительных блоков внутри ядра одинаково или нет? Что будет если программа откомпилирована для большего числа блоков, запустится ли она на меньшем?

hibou ★★★★★
() автор топика
Ответ на: комментарий от hibou

Получается, изменив число АПУ в будущем внутри одного ядра, они весь софт превратят в тыкву.

Да.

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

Не понял. Если речь про команды одного процесса, которые выполняются на одном ядре, то, очевидно, что распаралеллить их на разные EU не получится, откуда и берутся nop'ы в стартопосте, EU оказываются незадействованы, производительность далека от теоретического пика (который они везде гордо указывают). И то, что в фигурных скобках — это одна команда, и в кэше она целиком лежит. поэтому и конкуренции за кэш между EU нету.

gremlin_the_red ★★★★★
()
Ответ на: комментарий от hibou

число исполнительных блоков внутри ядра одинаково

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

Что будет

Если код скомпилен под большее число устройств, чем есть на проце - то не взлетит с invalid instruction.

Если под меньшее - есть варианты.

devl547 ★★★★★
()
Последнее исправление: devl547 (всего исправлений: 1)
Ответ на: комментарий от devl547

Благодарю за ответ! Еще бы подкрепить ссылками на документацию. И было бы совсем хорошо. :-)

hibou ★★★★★
() автор топика
Ответ на: комментарий от hibou

Что будет если программа откомпилирована для большего числа блоков, запустится ли она на меньшем?

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

gremlin_the_red ★★★★★
()
Ответ на: комментарий от gremlin_the_red

производительность далека от теоретического пика (который они везде гордо указывают).

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

no-such-file ★★★★★
()
Ответ на: комментарий от hibou

Или внутри одного ядра всегда фиксированное число АПУ, что на 1С, что на 8С?

Во 1-х, это за такт на 1 ядре, ты прикинь синхронизировать между ядрами, какая будет частоты при этом

В новых моделях число исполнительных блоков всё больше, хотя некоторые сохраняют их число

I-Love-Microsoft ★★★★★
()

И еще другая тема. Компилятор видимо еще не совсем доработан под Эльбрус.

Поскольку в ассемблерных листингах, которые генерирует lcc, внутри широкой команды обычно по 2-3 инструкции. Это означает, что блоки внутри ядра недогружены. Так, например, Эльбрус 1С за один такт может выполнить 25 команд. Ключевое слово «может». А исполняет 2-3.

Какое же здесь быстродействие?

hibou ★★★★★
() автор топика
Ответ на: комментарий от hibou

может выполнить 25 команд

В циклах, но только 9 идут в АЛК и кодируются 6 инструкциями, то есть если ты видишь 2-3 инструкции с АЛК на линейном коде, то это 33-50% загрузка ядра. Эльбрус не такой широкий как его рекламируют.

Современные x86 шире (Zen2 — 11 портов), но загрузить их возможно только кратковременно, когда reservation station заполнен разнообразными независимыми операциями (шлём привет SMT) ожидающими результатов длительных операций с одинаковым временем готовности.

anonymous
()
Ответ на: комментарий от gremlin_the_red

Это не твой вирт? Мне кааца вы оба нихрена не поняли ))) Но я не защищаю компилятор

В листинге отображается обычно не только команды, но и строки исходного кода. Вот на это бы посмотреть

Выше аноним верно указал, видно разбирается, я конечно мало что понимаю, но то что блоки разных типов существуют - это нужно понимать (прежде чем критиковать), и если действие требует не FPU а какого то иного, то загружены быть могут только блоки нужных типов. А другие только если у них есть задания

I-Love-Microsoft ★★★★★
()
Последнее исправление: I-Love-Microsoft (всего исправлений: 2)

Там не по количеству ядер, а по количеству АЛУ в ядре. С ненулевой вероятностью придётся.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от max_lapshin

Но написать этот jit будет очень больно и сложно.

Dark_SavanT ★★★★★
()

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

Puzan ★★★★★
()
Ответ на: комментарий от Dark_SavanT

В ответе будет и повторение того что написано выше, но всё-же.

В документации сказано, что одна такая широкая команда выполняется процессором за 1 такт.

А можно ссылочку на эту фразу? Потому что это просто не так - команда запускается на конвейер за один такт, а вот результат каждой инструкции в ШК будет готов за другое время (иначе в инструкциях nop не было бы смысла).

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

В ШК нельзя указывать ядро процессора (даже при желании штука неосуществимая). В ней указывается только номер исполняющего устройства на ядре.

Получается, что прогу для e2k придется пересобирать для разных e2k процессоров с разным числом ядер?

Нет, т.к. см. выше.

Если попытаться угадать суть вопроса, то ситуация будет следующая. Каждый процессор реализует конкретную версию СК (системы команд). С течением времени в ней может меняться количество исполняющих устройств и добавляться новые инструкции, что может вызвать некоторые трудности. Тем не менее все изменения проделываются так чтобы сохранялась прямая бинарная совместимость. Например, коды, собранные для Эльбрус-4С будут работать и на Эльбрус-8С и на Эльбрус-8СВ. Но при этом коды собранные для Эльбрус-8СВ на Эльбрус-4С уже не заработают по понятным причинам - обратная совместимость не поддерживается.

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

Окей, но на вопрос, по-моему, это не отвечает. Или внутри одного ядра всегда фиксированное число АПУ, что на 1С, что на 8С?

В конкретном примере - да, но в общем случае см. выше.

Благодарю за ответ! Еще бы подкрепить ссылками на документацию. И было бы совсем хорошо. :-)

Совсем недавно выложили хорошую документацию, рекомендую. Старую книгу указали в комментах выше.

И еще другая тема. Компилятор видимо еще не совсем доработан под Эльбрус.

Компилятор разрабатывается только под Эльбрус (ну и немного под Спарк).

Поскольку в ассемблерных листингах, которые генерирует lcc, внутри широкой команды обычно по 2-3 инструкции. Это означает, что блоки внутри ядра недогружены. Так, например, Эльбрус 1С за один такт может выполнить 25 команд. Ключевое слово «может». А исполняет 2-3.

В циклах, но только 9 идут в АЛК и кодируются 6 инструкциями, то есть если ты видишь 2-3 инструкции с АЛК на линейном коде, то это 33-50% загрузка ядра. Эльбрус не такой широкий как его рекламируют.

Эльбрус гораздо шире чем пытается представить комментатор. Во-первых Эльбрус содержит 6 универсальных АЛУ, но они нужны только для обычных вычислений (арифметика, обращения в память). Помимо этого в отдельных устройствах вычисляются логические значения, производится асинхронная подкачка массивов и подготовка передачи управления. Подробнее можно почитать тут.

У ТС код получился довольно разреженный, но это очень зависит от характера задачи, т.к. просто далеко не все задачи можно раскидать на параллельные вычисления. Но тут ко всему прочему неплохо бы посмотреть на сам исходник и опции сборки, т.к. это оказывает сильное влияние

можно вынести следующее: на таких процессорах очень полезно иметь JIT.

Да, это довольно актуальная задача, но пока что никем не решённая (были наработки для Итаниума, но их результат не особо впечатляет)

alexanius ★★
()
Ответ на: комментарий от alexanius

Пользуясь случаем. На вики для Э16С написано следующее:

Аппаратная поддержка динамической оптимизации

Счётчики для JIT? JIT для машкода/C/C++ или только для Java/JS/etc?

Это вы (МЦСТ) заполняете страниц на вики?

anonymous
()
Ответ на: комментарий от hibou

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

AKonia ★★
()

nop 2

nop 7

провал vliw-а уже в первом посте, неплохо

anonymous
()
Ответ на: комментарий от AKonia

взять серьёзную задачу с малым количеством зависимостей между командами, то загруз будет достойный, то же матричное умножение или какое-нибудь декодирование

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

anonymous
()
Ответ на: комментарий от anonymous

Счётчики для JIT? JIT для машкода/C/C++ или только для Java/JS/etc?

Для любого машкода, т.е. с прицелом на C/C++. В Java это и так давно реализовано.

Это вы (МЦСТ) заполняете страниц на вики?

Нет (возможно отдельные сотрудники по личной инициативе)

alexanius ★★
()
Ответ на: комментарий от alexanius

Благодарю за развёрнутый ответ!

Скажите пожалуйста, а опкоды (opcode) команд под Эльбрус можно где-то взять?

hibou ★★★★★
() автор топика
Ответ на: комментарий от hibou

Скажите пожалуйста, а опкоды (opcode) команд под Эльбрус можно где-то взять?

Уже где-то обсуждали. Пока что только брать lcc и реверсить выхлоп. В открытом доступе нет и видимо не предвидится.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от alexanius

с прицелом на C/C++

На какой это стадии? Есть замеры?

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

anonymous
()
Ответ на: комментарий от anonymous

это только шейдеры из игрушек

Так они даже там зафейлились, после чего AMD сначала понизили ширину с VLIW5 до VLIW4, а потом от собственно чистого VLIW отказались.

devl547 ★★★★★
()
Ответ на: комментарий от devl547

Трансмета машет рукой из гроба)

И Nvidia Denver/Denver2/Carmel c их DCO.

anonymous
()
Ответ на: комментарий от no-such-file

Обычный x86 хоть и имеет распараллеливатель, но он тупой. Компилятор всё равно должен тасовать команды под конкретный проц.

Продай свой пентиум ммх в музей и купи уже пентиум 2. Или АМД к6. Или cortex a9. Будет уметь тасовать команды сам, без помощи компилятора. Говорят, современные процессоры до нескольких сотен инструкций в очереди держат, а ты о расстановке команд компилятором под нагрузку АЛУ. Что толку их расставлять, если первый же доступ к памяти, который промахнется мимо кэша первого уровня, должен либо остановить всё исполнение до готовности данных (случай процессора без ooo), либо собьёт весь хитрый порядок команд?

Собственно поэтому Эльбрус и мертворожденный проект, VLIW тупо не подходит под систему с непредсказуемыми задержками.

khrundel ★★★★
()
Ответ на: комментарий от khrundel

Собственно поэтому Эльбрус и мертворожденный проект, VLIW тупо не подходит под систему с непредсказуемыми задержками.

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

anonymous
()
Ответ на: комментарий от max_lapshin

мне вот даже жаль

С исторической точки зрения - да.
С практической - девайсы были уж очень никакими по производительности. Жаль, что с софтовой частью и апдейтами CMS было не очень. Заопенсорсили бы - сообщество бы выжало всё что можно из JITа)

devl547 ★★★★★
()
Ответ на: комментарий от anonymous

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

Тактически все верно. У «нас» опыта разработки процессоров нет, зато куча кодеров. Наверное на это и был расчет, упросить логику в кремнии и пытаться выжать максимум силами программистов.

Aber ★★★★★
()
Ответ на: комментарий от Aber

Ну как бы да, но есть один побочный эффект. Если тупо взять и перекомпилять условный «ffmpeg» обмазанный SIMD интрисниками, то результат будет такой себе. Т.о. нужно оптимизировать специально под Эльбрус. И так чего не коснись. Т.е. конкретные задачи, если очень надо, то решать можно и даже вполне эффективно, но весь мир всё-таки не перепишешь.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Т.е. конкретные задачи, если очень надо, то решать можно и даже вполне эффективно, но весь мир всё-таки не перепишешь.

Да там даже boost coroutine2 не смогли портировать.

anonymous
()
Ответ на: комментарий от anonymous

Поскольку нет реализаций jump_fcontext() и make_fcontext(), без которых оно не работает.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.