| Предыдущая глава |
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |
было реализовать разные системы команд. А даже типично интерпретируемые
алгоритмические языки, как Бейсик или Ява (или даже такие типично
компилируемые как Паскаль) частенько реализуются трансляцией в некоторую
промежуточную форму ("пи-коды"), которые потом выполняются интерпретацией.
Да, языки программирования можно разделить на типично компилируемые и
типично интерпретируемые. Все компилируемые более-менее похожи друг на дружку и
на "аппаратную" ЭВМ (обычно называемую "машиной фон-Неймана"). Потому что
сделай в языке то, чего в компьютере нет, и будешь реализовывать это
интерпретацией! А вот интерпретируемые языки могут быть какие угодно...
Таким образом любой механизм в И_n, решающий не "единичную", а "массовую"
задачу, порождает своё собственное информационное подпространство И_n+1. Где
конечно могут быть только и исключительно данные. Но могут и механизмы. (Тогда
его смело можно называть "интерпретатором" или "эмулятором" некоторого языка.)
И тогда среди них тоже могут быть механизмы, порождающие собственные
информационные подпространства... Если ресурсов хватит: у реальных ЭВМ они
существенно ограниченные.
* * *
Абстрактные вычислительные устройства, у которых ресурсов заведомо хватит,
взялись изобретать где-то на границе XIX и XX веков. Когда математика решила
"подвести единый фундамент" под все свои разделы и выбрала для этого теорию
множеств. Ан, в ней обнаружились парадоксы! (Вот тот самый парадокс Рассела.)
Математики стали рвать на себе волосы и посыпать голову пеплом. Но некоторые
из них сказали, что всё дело в том, что мы работаем с "актуальными" множествами,
существующими сразу и целиком. А давайте займёмся "потенциальными", которые
будем строить поэлементно. Вот для этого и понадобились алгоритмы и абстрактные
вычислительные машины в качестве их исполнителей. Таковых было придумано штук
несколько: машина Поста, машина Тьюринга, нормальные алгориФмы Маркова...
Машины Поста и Тьюринга устроены почти одинаково: представляют собою
бесконечную в обе стороны ленту, разделенную на клеточки. (Типа магнитофонной,
хотя сам Пост представлял себе ряд ящиков.) И головку чтения/записи около
одной из них. На ленте и располагается обрабатываемая информация: у Поста
как набор нулей и единичек, а у Тьюринга — символов из ограниченного набора,
например букв и/или десятичных цифр. За один шаг машина выполняет одно из
следующих действий: передвигает головку к соседней ячейке, пишет в текущую
символ или считывает тот, что там находится и по его значению решает что ей
дальше делать. У Поста — только два варианта, а у Тьюринга — целая таблица.
Алгоритм (в виде этакой блок-схемы) располагается отдельно от обрабатываемых
данных. Но при желании тоже может быть закодирован некоторым образом и помещен
на ленту как входные данные.
Нормальные алгорифмы Маркова это фактически подстановки — замена слов
некоторого текста. (Если конечно "словом" считать любую последовательность
допустимых символов, тоже из ограниченного набора.) И соответственно от них
происходят все макрогенераторы. Фишка здесь — в "рекурсивности": в
подставляемом "слове" в качестве составной части могут быть и те слова, которые
ищутся и заменяются. (Не то, что в простеньком макрогенераторе предпроцессора
языка Си — директиве #define, где такого рекурсивного зацикливания быть не
должно.)
Есть еще взаимно рекурсивные функции и их абстракция "лямбда-исчисление", от
которых пошли функциональные языки типа Лиспа. А вот "клеточные автоматы",
наиболее известный из которых — игра "Жизнь", в те поры вроде бы всерьёз не
рассматривались.
Но через некоторое время во-первых выяснилось, что все они эквивалентны. Вот
как раз в том смысле что для каждой из них можно написать эмулятор любой другой
и выполнять на нём написанные для этой другой машины алгоритмы. А во-вторых там
тоже обнаружилась вот такая же как и в теории множеств особая точка: алгоритм
определения самоприменимости.
Вот мы возьмём некий конкретный алгоритм, отдадим ему на обработку некие
тоже конкретные входные данные и через некоторое число шагов получим результат.
(Возможно, через очень большое число шагов, но таки конечное: быстродействие
нас совершенно не волнует — машина то абстрактная!) Или не получим результат
никогда: алгоритм "зациклится" — так и будет бегать где-то там по кругу. Тогда
говорим, что он к этим данным неприменим. А теперь попытаемся применить
алгоритм к его собственной записи. На некотором языке, я так понимаю...
Эту самую задачу об определении самоприменимости я слышал в виде притчи о
Гениальном Кинорежиссёре и Безответном Монтажере. Которого он загонял так, что
общественность киностудии возмутилась и создала комиссию, взявшую на себя
функцию определять: выполнимы ли указания Режиссёра хотя бы в принципе.
А указания эти режиссёр повадился давать тоже снятыми на плёнку. (Да, расход
киноплёнки колоссальный, но ведь гений...) В конце концов режиссёр даёт такое
указание: отнести вот это на комиссию и если она решит, что указание
невыполнимо — смыть обе плёнки (рабочую и с указаниями) и на этом закончить.
А если решит что да — тогда отрезАть от рабочей плёнки последний кадр и
приклеивать его первым. То есть явное зацикливание. Посмотрели вторую рабочую
плёнку — там то же самое. Комиссия заседает до сих пор...
Для сравнения особая точка теории множеств это например каталог абсолютно
всех несамоназывающихся и только несамоназывающихся каталогов. (А сам этот
каталог должен быть в нём указан? Если да то он самоназывающийся,
следовательно не должен; а если нет — то несамоназывающийся: значит да!...)
Или например "задача о брадобрее": в изолированной непроходимыми джунглями от
остальной цивилизации крепости стоит полк, где все — мужики и у всех растёт
борода, но по уставу все должны ходить бритые. Для этого среди них есть
цирюльник имеющий право и квалификацию брить других. (А у всех остальных такой
лицензии нет.) И вот полковник, видимо чтобы облегчить ему жизнь, даёт строгий
приказ: брить тех и только тех, кто не бреется сам! Кто должен брить самого
цирюльника? Или, что то же самое — как ему не нарушить приказ полковника? Никак!
Или вот есть еще "парадокс лжеца": приехал тут с острова Крит один тип и
говорит что там все лжецы и нельзя верить ни одному ихнему слову. Но ведь он и
сам критянин!... Но тут по-моему встроенный дефект бинарной логики: если
добавить третье "неопределенное" состояние то никакого парадокса не будет.
Аналогично, если взять логический элемент с инверсией и соединить его вход с
выходом, то там будет не "единица" (каковой обычно является напряжение близкое
к напряжению питания) и не "ноль", а нечто среднее, промежуточное. (Кстати, сей
фокус частенько используется в электронике: соединив их резистором — загоняем
инвертор в "аналоговый" режим, где он работает как усилитель...)
Для практических целей используется то, что известно как машина Фон-Неймана:
европеи активно пытаются застолбить за собою первенство, хотя сами даже счеты
изобрести не осилили — узнали о них только от вернувшихся из плена солдат
Наполеона. А до того так и перекладывали камешки на древнегреческом абаке.
"Калькули" (считать) — дословно "гальковать"; галька — вот как раз мелкие
камешки.
Машина Фон-Неймана отличается от машины Лебедева тем, что не различает
программу и данные, вся информация для неё "на одно лицо" — какое действие вот к
данному конкретному слову применяется, значит то оно и есть: так проще сделать,
что было важно на начальном этапе развития вычислительной техники.
Соответственно, вся информация о типах данных и вообще их смысле "растворена" в
коде программы. В то время как машина Лебедева — с самоопределяемостью данных,
которая может быть на трёх уровнях: отдельных слов (к слову — небольшой довесок
"тег" (ярлык), указывающий что именно в нём хранится); на уровне агрегатов
данных (массивы, структуры, подпрограммы — "дескриптор" (описатель), описывающий
этот агрегат) и на абстрактном "объектном" уровне (объект "класс" на который
ссылаются все объекты — экземпляры данного класса и который содержит в себе
набор подпрограмм — "методов", "знающих" как выполнить над экземпляром класса
данное абстрактное действие.)
Но в принципе и та и другая состоят из четырёх частей, две из которых
"арифметико-логическое устройство" (АЛУ), собственно и выполняющее действия над
информацией и "устройство управления" (УУ) — решающее, какое именно и что делать
дальше, объединяются в "процессор". Память (ОЗУ) в виде ограниченного "адресным
пространством" ряда пронумерованных ячеек ("слов") — чисто пассивная: только
хранит информацию. А устройства ввода/вывода (УВВ) осуществляют взаимодействие
с внешним миром и как правило выглядят для программы тоже как ячейки памяти:
если туда что-то записать — это вызывает какое-то действие подключенного к
устройству эффектора. Или изменение во внешнем мире, зафиксированное датчиком,
меняет информацию в ячейке.
Соответственно, все задачи можно условно разделить на четыре класса: на
вычисления, на управление, на память и на интерфейс. Задачи на вычисления
исторически были первыми. И для них развивали в основном АЛУ. Впрочем и ЭВМ
были считанные единицы. (Монопольный режим, длинное слово; далее формат чисел
с плавающей запятой; отдельный процессор для них; а так же конвейерный принцип.)
При смене элементной базы с реле и ламп на диоды и транзисторы, и далее на
микросхемы всё большей степени интеграции, машина становится существенно
компактнее, надёжнее и дешевле. И гораздо доступнее. В результате резко
расширяется круг пользователей и решаемых ими задач... Следующими были — "на
память" (бухгалтерские): вычисления самые примитивные, но масса хранимой
информации пополам с текстом — базы данных. (Крупная ЭВМ и много пользователей,
развитая периферия — как для общения с ними, так и внешняя память; "пакетный"
режим выполнения задач и приглядывающий за ними монитор ("супервизор":
дословно надсмотрщик), привилегированные команды для его поддержки; слово,
разделённое на "слоги" — байты, для хранения в каждом одной буквы; межзадачная
защита памяти; примитивненькая система прерываний — чтобы внешнее устройство
могло потребовать обслуживания а не ждать, пока кто-то о нём вспомнит.)
Следующими пошли в ход задачи на управление — сначала простые но важные
(реактором, например, атомным или химическим), потом всё более сложные.
(Мини-ЭВМ с коротеньким словом и хорошо продуманной системой команд; развитая
система прерываний для быстрой реакции на внешние события; "открытая"
архитектура для добавления в том числе нестандартных внешних устройств;
задачи реального времени. А так как диалог с пользователем это тоже задача
реального времени, то многозадачные многопользовательские операционные
системы (в т.ч. UNIX) и средства аппаратной их поддержки, включая механизмы
виртуальной памяти.) Но для решения сложных задач управления (особенно
энерговооруженными объектами) этого недостаточно — требуется еще чтобы
аппаратура была "живучая" (продолжала функционировать даже при выходе части
её из строя, а так же по-возможности при программных ошибках), а программное
обеспечение — "надёжное" (разумно или по крайней мере не фатально вело себя и
в ситуациях не предусмотренных алгоритмом.) Для чего и понадобились машины
Лебедева, начиная с нашего Эльбруса... А вот для задач на интерфейс ничего
кроме "сырой" производительности и вот этих самых интерфейсных устройств не
требуется. И как мы туда вляпались, так и до сих пор не можем выбраться...
(Почему? Это уже совсем другая история: про глючную систему с обратными
связями типа "рынок", и то, как она в качестве стандарта де-факто выбирает не
лучший из предложенных образцов, а наихудший из работоспособных...)
* * *
Информация, определяющая форму реальных объектов, мало того что не
сохраняется, так еще и будучи предоставлена сама себе, имеет тенденцию
самопроизвольно изменяться более-менее случайным образом. (Что известно как
"энтропия".) В результате чего осмысленные вещи становятся менее осмысленными
просто потому что менее осмысленных информационных значений многократно больше,
а просто неосмысленных еще больше, при чем на много порядков. И вероятность,
что механизм после такой "мутации" будет работать не хуже а лучше, хотя и
ненулевая, но крайне мала. Но всё же используется эволюцией, которой в
результате приходится делать ну прямо таки астрономическое число попыток...
(Но даже этого, по некоторым расчетам, недостаточно. И есть подозрение, что
её "мутации" совсем не случайны...)
Некоторое количество информации сохраняется в кольце обратной связи. Хоть
положительной, хоть отрицательной. Поэтому всё далее рассмотренное — системы
вот с такими вот обратными связями.
Например электронный триггер — элементарная ячейка памяти на один бит, это
вот как раз два усилителя (с инверсией), выход каждого из которых подключен ко
входу другого. (Стоит подать питание, как один сразу "зашкаливает" — уходит в
насыщение, загоняя второго в отсечку. Какой — это как повезёт. И далее, пока
есть питание, сохраняют такое состояние. Если же того, кто в отсечке, из неё
вывести — триггер тут же перевернется в противоположное состояние...)
Ячейки "динамической" памяти представляют собою конденсаторы и информация там
хранится в виде заряда. Который постепенно утекает. Ну так время от времени
(пару тысяч раз в секунду) производится его "регенерация" — считывание и если
там хоть немножко осталось — "доливание" до полного. То есть обратная связь
тоже имеет место, хотя и "внешняя".
Но вообще время хранения информации определяется "прочностью" её носителя.
А в электронике есть и достаточно долговечные. Например это остаточная
намагниченность ферритового колечка, на которых раньше делали память ЭВМ.
И она тогда была энергонезависимая! Или "электронное болото" нитрида кремния,
"увязнув" в котором загнанные туда электроны будут выбираться из него лет сто.
Но посвети ультрафиолетом — болото разжижается и заряд утечет оттуда за пол
часика... Соответственно — ПЗУ с ультрафиолетовым стиранием и характерным
окошком для этого. Но и электрически перепрограммируемые ПЗУ, включая и то,
что называется "флэш-память" — на том же принципе. Но там электроны "выгоняют"
из этого "болота" так же как туда загоняли — высоким напряжением. (Относительно
| Предыдущая глава |
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |