Иван Савватеев @SIISII
Микроконтроллеры, цифровая электроника, ОС…
Information
- Rating
- 1,769-th
- Location
- Солнечногорск, Москва и Московская обл., Россия
- Date of birth
- Registered
- Activity
Specialization
Embedded Software Engineer
Lead
Микроконтроллеры, цифровая электроника, ОС…
Вроде бы, какие размеры должен иметь транзистор с такими параметрами, как современный, если его делать по образу и подобию более ранних, где нанометры ещё обозначали реальные размеры. Но утверждать не берусь -- я не специалист по микроэлектронному производству, да ещё суперпередовому :)
В 1980-е -- за счёт простоты процессора (грубо говоря, транзисторов меньше), что проистекало из примитивной системы команд (вдобавок, если сравнивать конкретно с Интелами, то у них система команд не особо-то эффективна -- в т.ч. из-за ужасного кодирования).
Сейчас -- из-за очень сложного декодера, о чём выше было сказано, но в сравнении есть определённое лукавство. Если будем сравнивать потребление энергии на выполнение какой-то элементарной команды (скажем, сложение), то при прочих равных у ARM оно будет сильно ниже. А вот если какое-нибудь шифрование нескольких килобайт данных... Современный AMD64/Intel 64 делает это, насколько помню, одной командой (IBMовские мэйнфреймы -- точно одно командой), на ARM же придётся шифровать программно, и кто меньше сожрёт в таких условиях -- уже большой вопрос, а если учесть ещё и потребное время на такую операцию...
Пы.Сы. А нанометры нынешние -- это маркетинг, к реальным размерам транзисторов они давно уже (где-то с рубежа 40 нм) отношения не имеют вообще.
Классическое микропрограммное управление никакого отношения к "трансляции сложных команд" не имеет, и декодирование у 8086 достаточно простое -- поскольку последовательное, байт за байтом, а не параллельное, да ещё для нескольких команд сразу, как в современных процессорах. На параллельное декодирование, учитывая бредовость интеловского кодирования команд, тогда банально не было ресурсов (транзисторов).
NEG -- это изменение знака, а не инверсия, а инверсия -- это NOT:
Так что это не фича, а именно что баг (собственно, Интел где-то это признала, насколько помню).
В разы ускоряется только операция выравнивания порядков перед сложением/вычитанием -- и то лишь если нужен очень длинный сдвиг, т. е. когда порядки отличаются очень значительно. Для умножения с делением выравнивание не требуется. А вот нормализация, которая может потребоваться после всех операций, требует предварительного определения положения крайнего левого единичного разряда -- а такой команды на тот момент не было, и его поиск сожрёт довольно много времени (ну или просто тупо сдвигать по одному биту, что при малом потребном числе сдвигов окажется даже быстрей). Ну и, естественно, само умножение-деление мантисс будет медленным, поскольку его придётся выполнять программно за отсутствием команд целочисленного умножения и деления.
В итоге, хотя операции и ускоряются по сравнению с процессорами, не способными сдвигать на много разрядов на один такт, но не так уж и сильно -- и в любом случае это намного медленнее, чем железный FPU.
Неверное понимание. Деление (как и умножение) за счёт сдвигов выполняется быстрее лишь в одном случае -- если делить надо на степень двойки -- но тогда и без быстрого сдвигателя сдвиг окажется быстрей, если степень не очень большая. Если делить надо на константу, не являющуюся степенью двойки, то иногда можно ускорить операцию, заменив деление на умножение, сложение-вычитание и сдвиги -- современные компиляторы это делать умеют. А вот если делить надо на произвольную величину -- тогда всё, только полноценное деление, и быстрый сдвигатель в этом случае никак не поможет.
Довольно много неточностей и искажений -- явно из-за любви автора описываемому продукту. Вот несколько штук навскидку.
Некорректно, если не добавить важное уточнение: с точки зрения программиста. Разрядность внутренних блоков, путей данных и т.д. и т.п. может быть любой. Скажем, сверхпопулярный в своё время Z80 имеет 4-разрядное АЛУ, хотя для программиста это 8-разрядный процессор. ЕС-1020, ЕС-1022, ЕС-1030 и ЕС-1050 реализуют одну и ту же архитектуру (32-разрядную IBM System/360), но у первой АЛУ 8-разрядное, у второй -- 16-разрядное, у третьей вообще дикая смесь всего (скажем, сумматор комбинация из 32- и 4-разрядного), а у четвёртой -- 64-разрядное, ну и так далее.
Ничего парадоксального: либо ты сразу формируешь широкий адрес (кстати, у ранних АРМов он был, насколько помню, 26-разрядным), либо должен городить какую-то дополнительную аппаратуру для преобразования логических (виртуальных) адресов в физические. Правда, в конце концов всё равно городить пришлось, чтоб обеспечить поддержку виртуальной памяти, но это произошло намного позже (вроде, только в ARMv5).
Он не сложнейший, он простейший. Проще почти что некуда -- собственно, это и стало одной из причин, почему удалось сходу сделать правильно. Плюс, конечно, нормально тестировали в процессе разработки (а вот Интел на это традиционно забивала, из-за чего, скажем, в 8086 команда инверсии не меняет флаги -- а должна была, как это делают все остальные команды обработки данных, ну а дальше уже приходится тащить сию "багофичу" из-за совместимости).
Аппаратное умножение отсутствовало даже в некоторых вариантах ARMv4, а деление появилось вообще лишь в ARMv7-M (а у микропроцессоров -- линейки -A -- оно отсутствует до сих пор; считается, что достаточно иметь FPU, который у -A есть, кажется, всегда).
И, кстати говоря, "устройство быстрого сдвига" никак не заменяет модуль для вычислений с плавающей запятой -- он лишь позволяет быстро производить многоразрядный сдвиг. Скажем, если команда требует сдвинуть значение на 5 разрядов, не надо пять раз выполнять однобитный сдвиг -- сразу будет выполнен требуемый. Вместе с некоторыми алгоритмическими трюками это позволяет ускорить подпрограммы, реализующие команды вещественной арифметики, но конкурировать с настоящим FPU всё равно не позволяет -- недаром его (FPU) в конце концов завезли даже в микроконтроллеры.
Скриншот из первой версии Принципов работы Системы 360, A22-6821-0.
Возможно, Вы спутали с тем, что сама защита ключами, как и интервальный таймер, в Системе 360 была необязательной (хотя де-факто присутствовала во всех "настоящих" моделях, кроме 30 и, может, 40 -- но и там была возможной, просто за отдельную плату).
Проблема в том, что Кобол так и не ушёл. Да и мэйнфреймы живее всех живых :)
Ну а синтаксис Це/Це++ был ужасным изначально, и дальше его лишь делали ещё более ужасным :(
В том-то и дело, что от изначальной трактовки идеи отошли. Против модульных систем я, понятное дело, ничего не имею, но микроядерными их не считаю как раз потому, что они не имеют никаких принципиальных отличий с точки зрения надёжности работы, организации внутренних связей и т.д. и т.п. по сравнению с абсолютно монолитными.
Кривые указатели никто не отменял, а без манипуляции ими действительно низкоуровневые вещи не сделаешь.
А вот тут Вы запамятовали: защита памяти ключами действует на каналы точно так же, как и на процессор, так что, если программа канала выполняется с ненулевым ключом (он указывается в CAW в момент запуска канальной программы), то залезть в чужую память не сможет.
Скорей, подтверждает мертворождённость самой изначальной идеи микроядерной ОС.
Не соглашусь. Дело не в едином адресном пространстве как таковом, а в отсутствии защиты областей, логически принадлежащих разным, скажем так, подсистемам (в упомянутой OS/360 отдельные пользовательские разделы и, тем более, области системы были защищены с помощью ключей, о чём Вы прекрасно знаете, поэтому общее адресное пространство не создавало проблем со взаимным вмешательством -- точней, не создавало бы, если бы не определённые дыры в самой ОС, но это уже вторично). Если, скажем, управление процессами, управление потоками, управление памятью и управление вводом-выводом (без учёта драйверов) реально не защищены от взаимного вмешательства -- всё, это не микроядерная ОС. Вынос драйверов в отдельные защищённые адресные пространства микроядерной её не делает -- изначальная идея была именно в полной изоляции каждой подсистемы от всех других и об их общении исключительно через микроядро. Ну а сейчас и Винду временами микроядерной называют.
В общем, в моей терминологии (опирающейся на изначальную идею, без учёта последующей "инфляции терминологии") реальных практически используемых микроядерных систем не существует. Так что изначальная Mach -- да, таки микроядерная, но практически бесполезная из-за диких накладных расходов, связанных с многократными переключениями контекста и переходами между режимами пользователя и ядра, почему от этой концепции на практике и отказались. А термин, наверное, тащат с рекламными целями: типа, наше православное эппловское микроядро -- это надёжно, в отличие от монолита в этой вашей безблагодатной винде или еретическом линухе (хотя реально тоже монолит делают) :)
Если же отвлечься от конкретно макоси и прочая, то, думается, с приемлемыми накладными расходами микроядро можно было бы реализовать за счёт использования сегментации IA-32 или механизма адресных пространств ESA/370/390/z/Architecture, где очень многие вещи делаются на уровне железа, без необходимости программного вмешательства. Но сама идея мне представляется мертворождённой: она не может обеспечить подлинную надёжность, ведь падение, скажем, подсистемы управления потоками не позволяет просто загрузить её заново с диска и запустить: при падении могут быть похерены критически важные данные (или, скорее, само падение произошло из-за того, что они уже были похерены из-за какой-либо ошибки в коде), а соответственно, и надёжный перезапуск без полной перезагрузки системы не представляется возможным. Даже падение драйвера не всегда позволяет разумным образом его перезапустить (скажем, нельзя "принимать на веру" находящиеся в очередях запросы ввода-вывода и прочие управляющие данные, касающиеся этого драйвера). В общем, для упрощения отладки -- вещь полезная (легче ловить выходы за границы логически доступной памяти), для реального повышения надёжности -- в общем случае бесполезная (хотя и полезная в определённых конкретных случаях: скажем, держать компилятор шейдеров внутри драйвера видюхи, выполняемого в режиме ядра -- ну, такое себе решение).
Вот только куар-коды для этого -- так себе идея. Как по мне, лучше всего классический виндузовый БСОД с распечаткой базовой информации прямо в текстовом виде.
МакОсь, насколько знаю, -- не микроядерная. Насколько помню, Mach там хотя и типа является микроядром, но вся реальная работа по обслуживанию обращений прикладных программ к системе выполняет подпиленное ядро от FreeBSD -- только оформленное как задача под управлением Mach, а не как собственно ядро. Т.е. формально можно заявить о микроядерности, но фактически реальное ядро -- это один большой модуль, а не куча изолированных друг от друга мелких задач. Т.е. полная профанация самой идеи микроядерности.
И, кстати говоря, то, что система А превосходит систему Б по производительности, не говорит о том, что базовые концепции системы А лучше концепций системы Б -- очень немаловажную роль играет качество реализации обеих систем. И относится это, естественно, не только к макоси и винде, а вообще ко всему.
Насколько помню, ограничение по времени -- только на добычу и доставку домой водяного чипа, когда это сделал -- всё, никаких тебе лимитов.
Вот когда разработчики сами, по собственному желанию (а не из-за каких-то дедлайнов, выдуманных манагерами) засиживаются допоздна, тогда на выходе и получаются шедевры.
Нету, ага. Просто я указал на то, что сей вариант отнюдь не "известен везде" -- хотя, вполне может быть, он известен куда большему количеству людей, чем Ералаш.
Ну, мне Ваш вариант неизвестен вообще и я так и не понял, в чём его суть :)
Микроядро реально не спасает в случае серьёзных сбоев: если упало что-то критически важное, то просто взять и перезапустить его нельзя, ведь причиной падения вполне могут стать кривые данные этого самого критически важного -- а их инициализировать заново, опять-таки, нельзя, поскольку они критически важны для работы системы (скажем, очереди запросов ввода-вывода, списки процессов и потоков и т.п. вещи). В реальности микроядерных систем, как это понималось изначально, вероятно, не существует. У той же QNX от изначальной идеи микроядра остался лишь вынос драйверов в отдельные процессы; все остальные функции традиционного ядра ОС (управление процессами, потоками, памятью, синхронизация и т.д. и т.п.) де-факто находятся в одном адресном пространстве и не защищены друг от друга. Но вынос драйверов или их частей возможен и в Винде; более того, часть драйверов и работает сейчас в пространстве пользователя. Скажем, бОльшая часть кода, относящегося к ГПУ, уже не часть ядра, и сбои в нём приводят лишь к падению определённых приложений (игрушка, например, вылетит), а не всей системы в целом.
У ГПУ, если не всегда, то обычно есть встроенные железные блоки для декодирования видео -- т.е. они это делают чисто аппаратно, а не программно, что и быстрей, и намного энергоэффективней. Есно, возможно и программная перекодировка, но она нужна, скажем, для какого-то нового алгоритма, не поддерживаемого в железе.
Если же говорить про чисто программную перекодировку, ГПУ с этим справляется лучше по скорости просто из-за того, что эта задача почти всегда очень хорошо параллелится. Обычные процы по своей натуре чисто последовательные, и наличие всяких дополнительных СИМД-команд лишь несколько увеличивает их "параллелизм" (и то, при условии, что программа умеет их использовать: толку от очередного новомодного SSE100500/AVX200600, если кодек был скомпилирован под базовую систему команд IA-32 (x86) без каких-либо SIMD-расширений?), в то время как ГПУ изначально созданы для параллельной обработки.
Качество же кодирования с видом проца прямо не связано -- оно зависит от конкретного алгоритма, используемого для кодирования. Если алгоритм абсолютно идентичен, то и результат будет абсолютно идентичен. Другое дело, что для ускорения или уменьшения объёма данных могут использовать определённые упрощения, допуская при этом некоторую потерю качества. Можно вспомнить, например, картинки JPEG, алгоритм кодирования которых позволяет играться с качеством результата и степенью сжатия изображения (чем меньше результат -- тем ниже качество). Но это, повторюсь, не от вида процессора зависит, а от особенностей алгоритма.
Я б сказал, не отказаться, а не использовать их там, где нужна высокая производительность или важна энергоэффективность. В общем, выбирать инструмент, исходя из задачи, а не из популярности.
Вообще, суперскалярные процы с внеочередным выполнением команд появились ещё в конце 1960-х, так что в этом плане ничего принципиально нового современные не представляют. А вот кода -- да, стало намного больше, причём зачастую в тех же самых задачах, что и полвека назад.
Абсолютно неверное утверждение. Команды вида ADD и ADC выполняются с абсолютно одинаковой скоростью и на абсолютно одном и том же оборудовании. Технически разница между ними заключается только в том, что в качестве входного переноса в ADD подаётся нуль, а в ADC -- значение переноса, запомненное при выполнении какой-либо предшествующей команды.
Ну и следует заметить, что эффективность подобных решений зависит от процессора, на котором предстоит выполнять программу. Скажем, на достаточно простых микроконтроллерах это в несколько раз снизит скорость работы, поскольку процессоры там не суперскалярные и выполняют команды последовательно.