Аннотация: Отсутствие формы само по себе есть форма; отсутствие содержания не есть содержание.
ны. Вопрос - зачем рассматривать такие вопросы, мы рассматривать не будем.
Если Вам не интересно - просто положите ЭТО туда, откуда взяли. Мы-же будем
действовать традиционным способом: дабы понять, как вычислительная техника
докатилась до нынешнего состояния, вспомним прошлое и попытаемся проследить
тенденции, буде таковые найдутся. И в резльтате ентого, вполне возможно, у
нас в мозгах обнаружится просветление.
ЧЕТЫРЕ ИСТОЧНИКА, ЧЕТЫРЕ СОСТАВНЫЕ ЧАСТИ... Как известно, вычислительная
машина (по крайней мере машина фонНеймана) состоит из процессора (ЦП) памяти
(ОЗУ, ПЗУ) и внешних устройств. В ЦП выделяют арифметическое устнойство
(АЛУ) и устройство управления (УУ). Часть внешних устройств это тоже память
(только внешняя - ВЗУ), остальные предназначены для связи с внешним миром.
(Интерфейсные устройства - ИУ.) Итого четыре основных части: АЛУ, УУ, *ЗУ,
ИУ, выполняющие четыре вида функций: "вычисления", "управление", "хранение"
(или "запоминание"), "интерфейс". Задачи тоже делятся на четыре группы, по
тому, какие функции в них преобладают. Деление достаточно условное - в любой
задаче встречаются все.
ИСТОРИЧЕСКИ первыми были задачи на вычисления. (Сколько урану должно быть
в каждом полушарии ядрёной бомбы, чтобы по отдельности не бабахнуло, а
только вместе?) Потому и название за машинами закрепилось -
"вычислительные". (Слово "компьютер" - тоже дословно "вычислитель", разве
что импортное.) И по сей день самые большие, самые мощные и дорогостоящие
супер-ЭВМ (каковых в мире считанные единицы) - типичные "мельницы для цифр".
Следующими были задачи "коммерчесские": вульгарно-бухгалтерские,
эксплуатируцие в основном память, и инженерные рассчеты рангом пониже, зато
куда как более массовые. "Большие" машины - это для них. И "пакетный" режим
вычислений (в отличии от монопольного) - тоже. Машинное время - оно дорогое
(было), а задачи, особенно бухгалтерские, не всё время считают - надо и
данные вводить, и ведомости печатать... А процессор в это время пусть
занимается следующей задачей пакета, созревшей для вычислений.
Следующий
этап - задачи управления. Сначала чем нибудь простеньким, но очень нужным.
Реактором например атомным. Здесь, как оказалось, особых вычислениний нет,
главное успевать вовремя реагировать на события, происходящие в реальном
времени. А у "больших" машин с этим делом - так-себе. Да и на подлодку такую
не затащишь. Потому специально для задач управления соорудили малые ("мини")
ЭВМ. Для чего сократили всё лишнее, в частности повыкидали громоздкие
внешние устройства, упростили систему ввода/вывода (надеюсь Вы помните, что
"усложнять просто, а упрощать сложно"!), уменьшили разрядность, систему
команд переделали руководствуясь туристским принципом: "брать с собой не то,
что может пригодиться, а только то, без чего нельзя обойтись". Команды и
форматы данных организовали так, чтобы собирать из них, как из кирпичиков,
всё что понадобится. Кое у кого получилось очень даже изящно. Машины вышли
действительно маленькие, простые, за счет этого довольно надежные... и
дешевые. В результате развелось их так много, что вычислительная техника
стала доступна даже студентам. А поскольку у мини-ЭВМ на роду написано
решать задачи реального времени, - придумали режим разделения этого самого
времени среди толпы народа, одновременно сидящей за множеством терминалов. И
оказалось, что хилых ресурсов какой-нибудь эСэМки вполне хватает: народ всё
больше тексты какие-то набирает, редко-редко кто счетную задачу запустит...
Ну и крутится она там в фоновом режиме. Кнопки-то народ нажимает медленно -
вот ей и перепадает иной раз до девяноста пяти процентов процессорного
времени.
Смену поколений обычно связывают с элементной базой: вот де первое
поколение было на лампах, а второе... Не то чтобы это совсем уж враньё:
ежели одна мелкосхема заменяет десять транзисторов, то это даёт возможность
либо сделать ту же самую машину в десять раз меньше, дешевле и надежнее,
либо сделать новую, содержащую в десять раз больше элементов. А уж на что их
употребить... Впрочем, всегда употребляли на то, что способствует: в первом
поколении ввели операции с плавающей запятой, придумали регистры, увеличили
разрядность. (Хотя она и так была не хилая.) Во втором - соорудили
виртуальную память а так-же средсва её защиты и поддержки операционной
системы, которая как раз понадобилась дабы надзирать за прохождением задач.
В третьем ввели средства оперативного реагирования на внешние события, в
т.ч. векторную систему прерываний. И при этом "упрощенная", "мини" машина
следующего поколения оказывалась только чуть слабее монстров предыдущего. И
отнють не примитивнее, скорее наоборот.
Но посмотрим, что было дальше. Дальше, с одной стороны, решив самые
простые задачи управления, и просто простые, народ взялся за по-настоящему
сложные и все даже заговорили об "искуственном интелекте". А с другой
стороны технологичесский прогресс наконец-то расстарался - соорудил
микропроцессоры пригодные чтобы их во что нибудь встроить, например в
робота, а не возить за ним на двух грузовиках. Так что появление этих самых
роботов (и прочих наделенных разумом вещей) ожидалось со дня на день. Но не
тут-то было! Грянуло то, что называют бумом персональных компьютеров. И
история прекратила течение своё.
Как только кривая стоимости аппаратуры, которая по мере развития
технологии довольно круто ползет вниз, пересеклась с кривой уровня доходов
отдельно взятого человека (которые всё время примерно на одном уровне) -
этот человек смог позволить себе приобрести вычислительную машинку в личное
пользование. Обнаружились и потребности, которые эта машинка может
удовлетворить. Конечно, они были и раньше, а то зачем было подключать к
мини-ЭВМ кучу терминалов?! Обнаружилась толпа народа, имеющая такие
потребности, очень большая толпа - почти всё население земного шара. А
главное, обнаружилось, что с одной стороны потребности эти столь примитивные
что для их удовлетворения вполне достаточно мощности восьмиразрядного
микропроцессора, а с другой - что у всех они одни и те-же. Последнее
означает, что каждому владельцу персональной машинки достаточно купить
только железо - стоимость программного обеспечения, которая как известно в
десятки, сотни... а то и сотни тысяч раз больше стоимости аппаратуры,
раскладывается на миллионы потребителей и на фоне железа почти не заметна.
Как только всё это обнаружилось - вот тут оно и началось.
Следует заметить, что все задачи, связанные с ПЭВМ - "на интерфейс". Оно
и понятно: персоналка должна облегчать, а не осложнять жизнь своему хозяину.
А хозяин её отнють не профессионал, и даже не дилетант, а... (ну не будем
говорить кто)... В общем чтобы он мог с ней справиться, надо чтобы
программное обеспечение само объясняло ему на какие кнопки нажимать.
МИКРОПРОЦЕССОРЫ, и микропроцессорные комплекты, на базе которых были
сделаны первые персоналки и архитектура которых "вморожена" в современные,
совершенно для этого не годятся. Они разрабатывались для изготовления
контроллеров - управляющих устройств, программа которых пишется один раз,
очень тщательно отлаживается и навечно зашивается в ПЗУ. Первые
микропроцессоры отличались очень маленькой разрядностью, очень низким
быстродействием и крайним примитивизмом. Быстродействие и разрядность со
временем увеличились, а примитивизм как был так и остался. Здесь сыиграли
роль как вполне объективные факторы (которые с развитием технологии
постепенно сошли на нет), так и субьективные: по причинам совершненно
непонятным разработчики микропроцессоров полностью отбросили весь
предшествующий более чем двадцатилетний опыт развития вычислительной техники
(или были настолько невежественны, что ничего о нём не знали), и принялись
по-новой набивать все те же самые шишки и наступать на те-же грабли, что и
их предшественники. Многие, включая небезызвестную фирму Intel не поумнели и
поныне, и вообще как видно горбатого только могила исправит! Для контроллера
дефекты архитектуры процессора, на котором он сделан, не слишком
существенны: средства защиты памяти и поддержки операционной системы
(которой в контроллере всё развно нет) - просто не нужны. Неудобство и
громоздкость управления внешними устройствами более-менее окупается
универсальностью микропроцессорного набора. А хилая и извратная система
команд... ну чтож, програмка-то пишется один раз.
Изначально и по сей день и сами персоналки, и программное обеспечение
к ним носят на
себе отпечаток этакой кустарности. Когда речь идёт об аглицком изобретателе
Синклере и его одноименной разработке, это было-бы вполне закономерно. Но
тут как раз чуствуется работа профессионала, сумевшего минимальными
средствами добился максимального эффекта, сделавшего конфетку из имевшегося
под рукой г. Для Синклера использование существующей элементной базы было
единственной возможностью. Для индустриального гиганта IBM, разработавшего
писишку - нет. Но они пошли по пути наименьшего сопротивления, и сделали это
по одной простой причине: им наплевать решительно на всё, кроме собственных
доходов. А чтобы их урвать надо обогнать конкурентов, что и было достигнуто.
Дальше начинают работать рыночные законы, делающие сколь угодно убогое и
недоношенное изделие стандартом de-facto. Разработчики программного
обеспечения, всячесские билы гейтсы, поступили в точности так-же.
Последующие почти два десятилетия так-же не выявили никакого прогресса.
Причина этого очень проста: как было указано раньше, персоналка решает
исключительно интерфейсные задачи. Можно даже сказать что это
гипертрофированный дисплей. А чтобы осуществлять этот интерфейс, даже такой
трудоёмкий как графичесский, в темпе восприятия человека, нужны
соответствующие интерфейсные устройства, а от процессора ничего особенного
не требуется, кроме разве-что "сырой" производительности. Потому с момента
появления первых микропроцессоров и по сей день никакого развития их
архитектуры не наблюдаеться. Реализовали (в весьма извращенном варианте)
достижения предыдущих поколений, и на том, как говорится, спасибо.
По нашему скромному мнению НЫНЕШНЕЕ СОСТОЯНИЕ ДЕЛ таково: бум
персональных ЭВМ подходит к концу. Более того - давно уже кончился, а сейчас
наблюдается гальванизация его трупа: имеет место заговор разработчиков
железа и программного обеспечения, цель которого вполне тривиальная -
"раскрутить пользователя на бабки". Мощность современных персоналок
совершенно избыточна, но разработчики железа всё равно упорно клепают всё
новые, всё более мощные и всё более дорогостоящие изделия (ибо цена
запущенного в серию ширпотреба, а это именно он, стремительно падает). Тем
временем билы гейтсы из кожи вон лезут дабы на практике убедить
пользователей в необходимости это железо покупать. Для чего ейные конторы
регулярно сооружают всё более громоздкие, ресурсоёмкие и монструозные
программы, основная функция которых - хоть на что нибудь употребить
избыточную производительность. От ранее существовавших аналогичных по
назначению программ (и от собственных более старых версий) они отличаются в
основном дополнительными красивостями, но зато на существующем железе еле
шевелятся. По отношению к ним слово "малоэффективный", если и применимо, то
служит уже не ругательным, а скорее хвалебным эпитетом.
Дело удалось повернуть так, что персоналка из инструмента превратилась в
предмет престижа, что и позволяет упомянутым халтурщикам обеспечивать
работой друг друга. И хотя до бесконечности это продолжаться не может, пока
не произойдет технической революции в смежных областях, здесь так и будет
продолжаться бег на месте. Так что сейчас на персоналках можно смело ставить
большой жирный крест. Пока речь идёт о деньгах - никакого прогресса здесь
небыло, нет и не предвидится. Тоесть прогресс в технологии производвтва
элементной базы - колоссальный, а в области архитектуры ничего не сдвинулось
и на милиметр. Впрочем есть "пентиум", но о нём разговор особый: снаружи он
остался всё той-же поганой писишкой, а вот внутреннее устройство процессора
действительно большой шаг вперед. Но и оно, как недавно выяснилось, содрано
с советской разработки начала восьмидесятых годов МВК "Эльбрус". (Впрочем о
нем речь еще впереди.) Жил да был такой гражданин Пентковский, участвовал в
разработке этого самого Эльбруса, даже книжку про евонный автокод написал.
Потом удрал на запад... Понятно теперь почему 586 процессор называется
именно так?
Если по существу - все интерфейсные задачи в основном решены и самое
время вернуться к отложенным задачам "управления".
Под "управлением" будем понимать не столько сами управляющие воздейсвия
на нечто "железное" - холодильник, станок с ЧПУ, трамвай, сколько
"мыслительные процессы", необходимые для формулирования правильных и
своевременных управляющих воздействий - формирования пристойного "поведения"
управляемого объекта. Ну, чтобы трамвай не только ехал по маршруту,
останавливался в положенных местах и открывал двери, но чтобы мог подождать
опаздывающего на него человека и чтобы, не дай бог, никого не задавил!
Задачи управления, как и любые другие, разделим по двум критериям: на
простые и сложные и на массовые и индивидуальные. (Разной степени сложности
и массовости.) При необходимости можно разделить и по третьему - степени
общественной значимости. Ну так вот: простые задачи и средней сложности, но
массовые, давно уже решены. Остались сложные и очень сложные - например этот
самый трамвай. Еще остались умеренно простые задачи, но индивидуальные. Имя
им легион. Каждый, поискав, найдет вокруг себя не один десяток того, что
можно было-бы автоматизировать. Но каждый случай требует индивидуального
подхода и потому считается, что "овчинка выделки не стоит". И по состоянию
дел на текущий момент это вполне справедливо. В двумерном пространстве задач
(одна координата - сложность, вторая - массовость) линия, отделяющая
решенные задачи от не решенных проходит по диагонали. И чтобы сдвинуть её с
места нужны особые предпосылки. Выявлением которых мы сейчас и займемся.
ЧТОБЫ ЗАДАЧИ РЕШАЛИСЬ надо чтобы стоимость их решения стала меньше
нежели получаемый от этого эффект. Эффект (как и стоимость) понятие весьма
расплывчатое. Будем считать что он пропорционален снижению трудозатрат
общества, проистекшего в результате внедрения этой штуки, помноженных на
общественную значимость области, где это происходит. А в стоимость решения
задачи кроме вполне очевидных затрат на этапах разработки, изготовления и
эксплуатации, включим еще и риск, проистекающий из-за того, что чем более
энерговооруженной является управляемая система, тем большие катаклизмы может
вызвать не только выход из строя управляющего ею механизма, но и
недостаточно корректная его работа. Если эффект зависит только от самой
задачи, то затраты можно попытаться уменьшить.
Как известно, управляющее устройство состоит из аппаратной и
программной компонент. Затраты на аппаратную компоненту наблюдаются на всех
этапах жизненного цикла системы. Но стоимость разработки и эксплуатации (а
это в основном ремонт) можно предельно снизить, используя модульность.
Тоесть один раз разработать функционально полный набор модулей, а потом
собирать из них управляющие устройства любой требуемой конфигурации как из
деталей детского конструктора. Тогда и ремонт сведется к простой замене
модулей. (Сами дефектные модули, если очень хочется, можно починять на
специализированном предприятии. Но проще и выгоднее сделать
неремонтопригодными - ведь не ремонтируют-же интегральные микросхемы!)
Стоимость изготовления аппаратной части можно уменьшить двумя способами.
Можно использовать особо простую и дешевую технологию, что предполагает
простоту и даже некоторый примитивизм изделия. А можно организовать
крупносерийное произвоство, позволяющее применить узкоспециализированное
высокоавтоматизированное высокопроизводительное оборудование. Это не требует
простоты изделия, но предполагает высокий уровень стандартизации и малую
номеноклатуру, что впрочем хорошо согласуется с модульностью.
Затраты на программное обеспечение наблюдаются только на этапе
разработки. Но программирование это сложный и малопроизводительный ручной
труд, не поддающийся никакой автоматизации, хотя попытки автоматизировать
его предпринимаются с момента появления вычислительной техники. Считается,
что программист способен в день написать не более десяти отлаженных
операторов на любом языке. На любом - в этом ключ к успеху. Хотя
автоматизировать процесс создания программного обеспечения пока не удается
(это сама по себе задача на управление, причем одна из самых сложных), но
можно его облегчать и упрощать, предлагая программистам в качестве
инструмента языки всё более высокого уровня (ЯВУ). Программирование это
борьба со сложностью - преобразование качественной сложности решаемой задачи
в количественную сложность машинного кода, преодоление разрыва между
уровнями машинного языка и языка, на котором задача формулируется. Чем
меньше этот разрыв (обычно называемый "семантическим"), или чем большая его
часть преодолевается с помощью системного программного обеспечения -
компиляторов, ассемблеров, редакторов связей, отладчиков, тем проще задача
для программиста.
Для умеренно ПРОСТЫХ, НО ИНДИВИДУАЛЬНЫХ задач требуется очень дешевая и
легкодоступная аппаратура и очень простое программирование её. Если
количество ПЭВМ в идеале соизмеримо с численностью населения земли, то
количество устройство этого класса (опять-же в идеале) должно быть на два -
три порядка больше. А так как задачи по определению индивидуальные, то
полная
стоимость решения каждой должна быть во столько-же раз меньше. И решать их
придется преимущественно самим потребителям. Тоесть надо чтобы собрать
вычислительное устройство для управления, ну например освещением в комнате,
мог любой мужик, способный забить в стенку гвоздь или починить утюг; а
запрограммировать - любой восьмикласник, изучивший в школе начала
информатики более чем на тройку. И всё это - за два выходных дня.
Средства снижения стоимости аппаратной части - не просто модульность,
стандартизация, унификация, малая номеноклатура, массовое производство, но
всё это в превосходной степени. Комплект модулей должен состоять не более
чем из 10 - 15 наименований. В него очевидно должны входить силовые ключи,
средства сопряжения с датчиками разного типа (то и другое с гальванической
развязкой), средства генерации временных последовательностей, средства
сопряжения с органами управления и устройствами индикации, средства
межмашинного интерфейса, а так-же сам процессор, долговременная
энергонезависимая память (репрограммируемое ПЗУ) и конечно источник питания.
Сборка управляющего устройства из модулей должна производиться без
изготовления дополнительных деталей (типа печатных плат), без применения
какого бы то ни было промышленного оборудования, почти без пайки, буквально
с помощью ножниц и клея. Но при этом от управляющего устройства не требуется
ни высокого быстродействия, ни большой памяти, ни особо высокой надежности.
Так - на уровне программируемого калькулятора. Это дополнительный резерв
снижения стоимости железа. (Например можно применить p-МОП логику,
медленную, требующую "неудобного" питания, зато дешевую и помехоустойчивую.)
Простота программирования с одной стороны обеспечивается простотой,
обозримостью и хорошей документированностью железа (следствия высокой
унификации и малой номеноклатуры). А с другой - резким сокращением
семантического разрыва между языком, на котором будут писаться программы и
уровнем машинного кода. Причем не со стороны языка (что означало-бы, что
программы пишутся на ассемблере) а с противоположной - программы всё равно
пишутся на асемблере, а при желании - прямо в кодах, только это (и коды
тоже!) язык высокого уровня. Высокоуровневая архитектура оплачивается
дополнительными аппаратными затратами - повышением сложности процессора и
интерфейсных устройств. Однако при современном уровне технологии это вполне
можно себе позволить.
Простоты программирования можно, конечно, достигнуть и с помощью
кросс-средств. Тоесть сделать для ПЭВМ мощный и достаточно удобный
кросс-компилятор с какого нибудь языка высокого уровня. (С Ады например.
Имено для этого её и разработали.) Да хоть с Бейсика! Но это худшее, что
можно придумать. Поэтому (не приведи бог!) возникнет такая возможность -
биллы гейтсы тут-же за неё ухватятся: если семантический разрыв будет
перекрываться в основном с помощью компилятора - программист утратит "чуство
машины", доступное только "кодокопателям" (вернее никогда его не
приобретёт!), об эффективности кода можно будет сразу забыть, значит для
решения той-же самой задачи потребуется во много раз больше ресурсов -
памяти и быстродействия. А всё это в конечном итоге цена, габариты,
энергопотребление. Ну и разумеется, сложное, громоздкое, дорогое системное
программное обеспечение, подверженное влиянию моды. А не того-ли они
добиваются?
Кроме того, примтивная низкоуровневая архитектура всё равно находит своё
отражение в компилируемом языке, чрезмерно усложняя его. Пример тому
упомянутый язык Ада - другого такого монстра еще поискать! А
программирование это и так борьба со сложностью. И если к сложности задачи
добавится еще сложность инструмента для её решения - проэкт развалится так и
не начавшись.
Сложные и очень сложные задачи (их еще называют "большими") находятся на
пределе возможностей как человека, так и машины: количество деталей таково,
что не помещается в "оперативную память" одного человека, а сами задачи
столь сильносвязные, что не удается разбить их на обозримые части; для
формирования управляющих воздействий требуется выполнения такого количества
операций, что программа едва успевает; а сама программа вместе с данными
едва-едва помещается теперь уже в оперативной памяти машины. Использование
вычислительных устройств, имеющих большую память и быстродействие
лимитируется их массой, габаритами, энергопотреблением, стоимостью. (А часто
таких просто нет.) Так что метод "грубой силы", столь любимый американцами,
исключен. Кроме того, для большинства задач этого класса риск так-же
находится на пределе общественно допустимого.
Такие задачи разрешимы уже сейчас, но решаются только если их
общественная значимость очень велика (что наблюдается в военной и
космической областях). Управление "Бураном" - да, управление трамваем - нет.
ЧТО ДЕЛАТЬ - давно и хорошо известно: для снижения риска требуется
живучая аппаратура и надежное программное обеспечение; для уменьшения
сложности задачи - очень высокоуровневые инструменты, примитивы которых по
возможности приближались-бы к понятиям, которыми мыслит сам программист, а
не наоборот; ресурсоёмкость задачи уменьшается повышением эффективости
выполняемого кода. Всё хорошо - одно плохо: эти рецепты противоречат друг
другу.
ЭФФЕКТИВНАЯ программа, это та, которая решает ту же самую задачу, но
тратит на это меньше (или гораздо меньше) ресурсов: занимает меньше места в
памяти и/или на диске, работает быстрее... или лучше - принимает более
удачные решения (впрочем это уже эффективность на следующем уровне).
Ресурсов не жалко, если они в избытке. А когда в обрез? Эффективность
программы зависит от многих вещей: и от общей постановки задачи, и от выбора
алгоритмов... (Даже гвозди можно по-разному забивать; можно и шляпкой
вперед, только не эффективно.) Здесь есть два подхода - инженерный и
изобретательский. Инженерный - улучшить одни параметры (которые критичны) за
счет других, которыми в данной задаче можно поступиться. Например можно
обменять быстродействие на память, или более глобально - производительность на
универсальность. Изобретательский подход - сделать так, чтобы и волки были
сыты, и овцы целы. Это получается далеко не всегда и далеко не у всех:
инженерия - ремесло, а изобретательство - искуство. ...Но и процесс
превращения алгоритма в код (тоесть собственно программирование) тоже
оказывает на эффективность получаемой системы очень существенное влияние. (А
иногда и решающее - плохой реализацией можно угробить самую лучшую идею.)
Главную роль при этом играет уже упоминавшийся семантический разрыв. Чтобы
программа была эффективной - её надо писать на ассемблере, а в идеале - в
кодах. Тоесть чтобы разрыв между кодами и языком был как можно меньше.
Только тогда удается осознать, учесть и использовать все особенности
аппаратуры, почуствовать, чего на самом деле стоит каждое действие,
максимально оптимизировать код. Но это требует особо высокой квалификации от
программиста, и на него-же ложится вся нагрузка по преодолению
семантического разрыва. При этом количество деталей, объём программы, а
значит трудоёмкость написания и отладки возрастают неимоверно. К тому-же
падает надежность программирования, впрочем о ней чуть позже. Нет, чисто на
ассемблере даже весьма средненькую задачу решать тяжко.
Чтобы облегчить написание и отладку программы, снизить её объём и
сложность, повысить производительность труда програмиста, увеличить
надежность, добиться переносимости программы, и много еще для чего - надо
использовать средства (языки) как можно более высокого уровня. Все так и
делают. Тоесть сокращают разрыв сверху, увеличивают снизу, перекрывая его
средствами системного программного обеспечения (ОС, компиляторы,
высокоуровневые отладчики). Про эффективность можно и не вспоминать. Но
приходится - тогда наиболее критичные части опять пишут на ассемлере и тем
немножко спасаются. Но всё равно приходится использовать сложное,
громоздкое, ресурсоёмкое дорогое системное программное обеспечение,
генерирующее в точности такие-же программы. Единственный выход - добавить
системе ресурсов - путь грубой силы, который нам заказан.
Теоретически можно поступить наоборот - сократить разрыв снизу,
реализовав в аппаратуре высокоуровневые примитивы. Как уже было сказано, это
оплачивается резким усложнением и удорожанием аппаратуры. А может не таким
уж резким? Всерьёз почти никто не пробовал. А кто пробовал - эти машины у
них "не пошли". По разным причинам, как правило никакого отношения к
вычислительной технике не имеющим. (Примеры - наш Эльбрус (на котором и
реализована система управления Бураном). А из буржуйских (двадцатилетней
давности) те, что описал в своей книге преподобный Майерс: iAPX-432, SYMBOL,
SWARD, system-38 и некоторые другие. Последняя (разработка фирмы IBM ) -
вопиющий пример
идиотизма. Надо-же было додуматься, соорудить машину с одноуровневой памятью
и самоопределяемостью данных
для решения бухгалтерских (!) задач, реализовав на ней Кобол и РПГ. Ещё бы
она у них пошла!)
НАДЕЖНОСТЬ программного обеспечения - свойство вполне загадочное.
Интуитивно понятно, что надежная программа, это та, на которую можно
положиться, которая, если что, не подведёт. Конечно, надежная программа
хорошо отдресирована и правильно работает - в точном соответствии с
замыслами её автора. Но она не психует и при аппаратных сбоях, а так-же по
поводу собственных ошибок (каковые все, хоть тресни, не выловишь, особенно в
"большой" программе). А в ситуациях автором вовсе и не предусмотренных ведет
себя не слишком фатально, или даже вполне разумно. Как этого добиться -
тайна великая есть. Здесь тоже играет роль абсолютно всё - и постановка
задачи и поиск/выбор/изобретение надежных (а за одно и эффективных)
алгоритмов, ну и конечно отладка.
Как "электроника - это наука о контактах",
так и программирование - это борьба с ошибками. Ошибками считаем что угодно
- и некорректную (в некоторой своей части) постановку задачи, и не слишком
удачный выбор алгоритма (что имеет тенденцию обнаруживаться когда программа
давно написана, отлажена и уже года два как эксплуатируется), ну и конечно
программные ошибки, которых сорок сороков разных видов. Лемма: "в любой
программе найдется хотя-бы одна ошибка" ни откуда не следует, но всегда
выполняется. Даже в предельном случае, когда программа (нетривиальная!)
состоит ровно из одной машинной команды. Что было проверено
экспериментально.
Грамматические ошибки отлавливает компилятор, большая часть смысловых
(семантических) выявляется на этапе приведения программы в соответствие с
замыслами автора (т.е. основная часть отладки), кое-что удается выявить в
ходе тестирования уже почти готовой программы, но количество оставшихся
ошибок, как и количество атомов радиоактивного вещества, уменьшается
экспоненциально от времени (усилий) затраченных на отладку, и не становится
равным нулю никогда. (Так, что даже можно ввести понятие "время полуотладки"
аналогично с "периодом полураспада".) Даже у весьма средненькой программы
столько щелей и закоулков, что вымести оттуда весь мусор и выгнать всех
тараканов как правило не удается. Вот они и вылезают во время эксплуатации.
Делались (и сейчас видимо продолжаются) попытки разработать способы и
системы "верификации" программного обеспечения, т.е. формального
доказательства "правильности" программы. Доказать правильность программы
конечно можно, но это на один - два порядка сложнее, чем просто написать эту
программу и отладить. А делать это автоматически - таже самая задача, что и
автоматичесское написание программ. Флаг им в руки!
Программирование на языках высокого уровня (ЯВУ) повышает
надежность уже тем, что снижает сложность, облегчает понимание и следовательно
отладку программы. Кроме того, компилятор наряду с грамматическими ошибками
(выявлять которые его святая обязанность) пытается обнаружить и некоторые
смысловые - на подобии использования значения переменной, которой еще ничего
небыло присвоено. А для борьбы с некоторыми видами ошибок времени выполнения,
типа выхода индекса за границы массива, умеет вставлять
в генерируемый код разнообразные проверки. Это тоже повышает надежность, но
сильно увеличивает объем кода (и соответственно снижает скорость
выполнения программы). Особенно обидно, что этот код действительно приносит
пользу только при возникновении ошибки, что бывает весьма редко (в идеале -
никогда), а в остальных случаях (тоесть почти всегда) просто занимает место и
время. И немало. Можно бы его конечно использовать только на время отладки,
а потом отключить, но это всё равно, что обучаясь плавать в бассейне
надевать спасательный жилет, а поплыв через океан оставить его дома.
Лучше всего было-бы возложить эти проверки на аппаратуру - она, в
отличии от программы, работает параллельно. Но для этого "индекс", "массив" и
его границы, (за которые выходить нельзя, а то будет ой), и многие другие
понятия, связанные с тем, что надо проверять, должны быть реализованы на
уровне аппаратуры. Сделано это только в нескольких, перечисленных выше,
вычислительных системах. А для всех остальных массив - это просто область
памяти, ничем не отличающаяся от соседних; индекс - просто целое число, никак с этой областью
памяти не связанное; потом индекс будет преобразован в адрес (умножением на
одну константу (размер элемента массива) и сложением с другой (адресом
начала)), но сделает это программа, а процессор просто тупо выполнит
предписанные ею операции. Проконтролировать выход индекса за границы массива
можно и здесь - для этого надо чтобы область памяти, занимаемая массивом,
имела аппаратно доступные границы. Например, если у
машины есть "настоящие" сегменты (как у x86 в защищенном режиме), достаточно
разместить массив в отдельном сегменте. Звучит неплохо. Но разве так
кто-нибудь делает?! Ведь персональный сегмент надо предоставить КАЖДОМУ
массиву,
в том числе и локальному, размещаемому в стэке. А распределять селекторы
сегментов и следить за их освобождением кто будет? Что, опять программа?!!
Вот то-то. Ну и на хрена, спрашивается, эти сегменты нужны? Разве-что
осложнять программистам жизнь, и без того тяжелую. А ведь это только один
класс ошибок, далеко не самый существенный. "Висящие ссылки" куда опаснее.
ЖИВУЧЕСТЬ достигается введением избыточности. Самое
простое - резервирование. Тоесть каждый блок или всё устройство целиком
присутствует в двух, а лучше в
трёх экземплярах. Один экземпляр работает, другие ничего не делают - ждут
когда первый сломается, но энергию потребляют. (Годится только "горячее"
резервирование!) А еще требуются средства контроля исправности переключения
на резерв. Про массу, объем и стоимость можно и не говорить.
Возможен и другой вариант - многопроцессорные вычислительные системы:
вместо одного большого устройства,
единолично выполняющего всю работу, - много маленьких, делающих её
коллективными усилиями. При выходе из строя одного члена коллектива, его часть
работы должны взять на себя оставшиеся. Такая вычислительная система будет не
только живучей, но и "расширяемой" - при необходимости можно повысисть
мощность до требуемых пределов просто добавляя в систему новые элементы.
Разумеется, это гораздо лучше резервирования, но и реализуется гораздо
сложнее. Сразу встает вопрос - как распределить работу между множеством
исполнителей? Особенно, если учесть, что программы традиционно пишутся как
ПОСЛЕДОВАТЕЛЬНОСТЬ действий.
Многопроцессорные системы
со статичесским распределением работы, наиболее выдающимся представителем
которых являются "транспьютеры", понятное дело не годятся. Там при изменении
конфигурации (как в результате добавления нового процессора, так и выхода
из строя одного из имеющихся) требуется перекомпилировать программу.
(А самолёт, которым эта штука управляла, в это время летит!)
Другой не менее существенной (хотя и не слишком заметной на первый взгляд)
проблемой является доступ к общим для всех ресурсам. Это прежде всего простран