Язык потоков данных
Прежде чем изучать архитектурные особенности машин потоков данных, рассмотрим более подробно сам принцип обслуживания этими машинами потоков данных на уровне языка программирования. С этой целью ознакомимся со специальным языком, предложенным Деннисом' и его коллегами из Массачусетского технологического института [4—6], где проводятся наиболее серьезные исследования в области машин потоков данных.
Хотя язык Денниса является языком двумерного графического описания объектов программирования, существуют и другие предложения по построению подобных языков [7—11], предполагающие представление программ потоков данных в более привычном виде—в форме последовательности операторов, подчиняющихся определенному синтаксису такого языка.
Как упоминалось выше, в языке потоков данных не используются понятия «переменная» и «передача управления». Программа записывается в виде набора операторов, активируемых данными и соединенных однонаправленными линиями передачи. В основу языка Денниса положены следующие три основных понятия: исполнительный элемент, информация и линия связи.
Исполнительный элемент символизирует операцию, готовую к выполнению при поступлении информации на входные линии этого элемента и при отсутствии информации на его выходных линиях. Существуют два типа исполнительных элементов — блоки (actor) и размножители (link). Блок—это исполнительный элемент с одной выходной линией и одной или несколькими входными, размножитель—с одной входной линией и несколькими выходными.
Информация в языке Денниса представляется в виде токенов, которые передаются по линиям связи, обрабатываются it выдаются исполнительными элементами.
Различают два основных вида информации: значения данных (например, числовые величины) и значения управляющих сигналов (логические величины TRUE — ИСТИННО или FALSE — ЛОЖНО). В описываемом языке отсутствуют средства для распознавания типов значений данных (целые, с фиксированной точкой, с плавающей точкой, комплексные и т. д.). Некоторые расширения языка, связанные с обработкой структур данных, рассматриваются в одном из следующих разделов.
Рис. 22.4. Исполнительные элементы графического языка.
Используемое в языке Денниса понятие линия связи (arc) символизирует однонаправленный тракт, по которому информация передается от одного исполнительного элемента к другому. Сигналы на линии связи могут отсутствовать либо на ней может находиться только 1 токен информации. Следовательно, линию связи можно рассматривать как определенный эквивалент традиционных понятий «переменная» и «область памяти». В соответствии с классификацией информации на значения .данных и значения управляющих сигналов линии также разделяются на линии данных (обозначены на рисунках сплошными стрелками) и управляющие линии (обозначены штриховыми стрелками). На рис. 22.4 изображены исполнительные элементы языка: сплошные стрелки показывают места подсоединения линий данных, штриховые—управляющих линий. Операция размножения готова к выполнению при появлении токена на единственной входной линии размножителя и при условии, что все его выходные линии пусты. Размножитель распределяет полученный токен по выходным линиям. Блок выполнения операции обычно имеет одну или две входные линии. Блок готов к работе при наличии токенов данных на всех его входных линиях и при условии, что выходная линия пуста. Он принимает входные токены, выполняет некоторые преобразования над полученными величинами и помещает результирующий токен данных на свою выходную линию. Типичными операциями таких блоков являются сложение, вычитание, умножение, инвертирова-1ие, извлечение квадратного корня и т. д.
Блок принятия решения функционирует аналогичным образом, однако результатом его работы является управляющий сигал (логическая величина). В этом блоке вычисляется отношение, составленное из выходных данных, и формируется результат в виде логической величины TRUE (ИСТИННО) или FALSE (ЛОЖНО). Типичными операциями отношения являются операции сравнения двух величин по одному из критериев типа «равны», «не равны», «первая величина больше второй» т. д.
Остальные три блока имеют на входе и данные, и управляющие сигналы. Блок типа вентиль Т (Т—от английского слова TRUE) готов к работе при наличии на его входах как токена данных, так и токена управляющей информации (при )м, как обычно, выходная линия должна быть пуста). Как и все остальные исполнительные элементы, этот блок «поглощает» входную информацию во время выполнения. Если значение являющего сигнала TRUE, то имеющийся на входе блока токен данных передается на выходную линию. Если значение управляющего сигнала FALSE, то сигнал на выходе блока не формируется. Таким образом, вентиль Т либо пропускает вход-данные на свой выход, либо просто «поглощает» их. Блок типа вентиль F (F—от английского слова FALSE) работает аналогичным образом, только для передачи токена данных на выходную линию требуется управляющий сигнал, имеющий значение FALSE.
Среди различных блоков рассматриваемого языка потоков данных блок типа «смеситель» является исключением: выполнение предписываемых им действий не вызывает уничтожения токенов на входных линиях, и для перехода его в состояние готовности к работе не требуется наличия всех входных токенов. Этот блок готов к работе при соблюдении одного из следующих условий: 1) одновременное присутствие управляющего токена TRUE и токена данных на линии с меткой Т; 2) одновременное присутствие управляющего токена FALSE и токена данных на линии с меткой F. В обоих случаях выходная линия должна быть пуста. Если присутствует управляющий токен TRUE, токен данных с входной линии Т пересылается на выходную линию. В результате эти два токена на входных линиях уничтожаются, но при наличии токена данных на линии F он сохраняется. Если присутствует управляющий токен FALSE, то токен данных на входной линии F пересылается на выходную линию. В результате этого два токена на входных линиях уничтожаются, но токен данных на линии Т, если он присутствовал, сохраняется.
Свойства рассматриваемого языка нагляднее всего можно продемонстрировать на примере выполнения программы. Простая программа, выбранная для изучения, сначала записывается на языке типа ПЛ/1:
Z: PROCEDURE (X,Y);
DO I=1 TO X;
IF Y>1 THEN Y=Y*Y;
ELSE Y=Y+Y+2;
END;
END;
Представление этой программы на языке потоков данных показано на рис. 22.5. Такая форма представления выглядит более громоздко, чем приведенная выше процедурная запись Однако следует иметь в виду, что язык потоков данных еще не сформулирован окончательно и вполне возможно, что со временем будет разработан синтаксис этого языка, более традиционный по форме.
Рис.22.5. Графическое представление программы потоков данных.
Сопоставляя рис. 22.5 с программой на языке, подобном языку ПЛ/1, можно установить их взаимное соответствие. Левая часть рис. 22.5 представляет собой в основном тело цикла DO; правая часть отображает выполнение оператора DO. Отметим, что некоторые блоки имеют на входных линиях константы. Смысл этого заключается в том, что как только блок выполняет предписанную ему работу, константа вновь автоматически воспроизводится на линии.
Рис.22.6. Начальное состояние программы.
Рассмотрим выполнение программы на языке потоков данных при значениях входных переменных Х и У, равных 2 и 0 соответственно. Прежде всего программа должна быть приведена в некоторое начальное состояние путем задания на графе определенных управляющих токенов. На рис. 22.6 показано такое начальное состояние программы. Управляющие токены на управляющих входных линиях трех смесителей в верхней части схемы имеют начальные значения. Управляющие токены и токены данных обозначаются на рисунках явным указанием их значений.
Рис.22.7. Состояние программы в момент А.
В соответствии с начальным состоянием программы, отображенным на рис. 22.6, три блока готовы к работе. Смеситель, расположенный вверху слева, готов к выполнению своих функций, поскольку к нему приложен управляющий токен FALSE, а на его входной линии F имеется токен данных. Два других смесителя находятся в состоянии готовности по тем же причинам. Таким образом, при наличии соответствующих аппаратных; средств, реализующих архитектуру машины потока данных, эти три смесителя могут функционировать параллельно. Для обсуждения здесь хода выполнения программы следует рассматривать работу каждого блока шаг за шагом, принимая во внимание, что, во-первых, в каждый момент времени несколько блоков могут быть одновременно готовы к работе, т. е. обеспечена возможность их параллельной работы, и, во-вторых, ход выполнения программы не зависит от того, в каком порядке функционируют готовые к работе блоки (если вообще существует какой-либо определенный порядок их функционирования).
Далее следует пропустить эти значения входных величин через программу, пока не будет получено значение результата н, выходной линии. Поскольку пошаговый анализ этой процедур1 займет много времени и весьма утомителен, ограничимся рас смотрением нескольких «мгновенных снимков» состояния программы в процессе выполнения указанных действий.
Результатом работы смесителя, находящегося вверху слева является передача величины 0 через размножитель на шест] входных линий других блоков. В результате работы смесителя расположенного справа, величина 2 через размножитель поступает обратно на вход Т того же смесителя и, кроме того, на блок принятия решения. Работа среднего смесителя завершается подачей величины 1 на исполнительный блок и блок принятия решения.
Полученное в результате описанных действий состояние программы—первый «мгновенный снимок»—показано на рис. 22.7. Теперь пять блоков готовы к работе и могут функционировать параллельно. Блок принятия решения по критерию «первый операнд отношения больше второго» формирует управляющий токен FALSE, который посылается в три блока: вентили Т и F и нижний смеситель. В результате срабатывания блока принятия решения по критерию «первый операнд отношения меньше или равен второму» формируется управляющий токен TRUE, направляемый четырем адресатам. Блок операции сложения, расположенный в середине схемы, также готов к работе, он пошлет величину 2 обратно на вход среднего смесителя. Эта операция сложения эквивалентна сложению внутри цикла DO в программе на языке, подобном языку ПЛ/1.
Рис.22.8. Состояние программы в момент Б.
Рис.22.9. Состояние программы в момент В.
На рис. 22.8 приведен второй «мгновенный снимок», отображающий следующее состояние программы. В этот момент готовы к работе три вентиля. Поскольку вентиль F, являющийся источником данных для выходной линии программы, имеет управляющий токен TRUE, величина 0 будет просто «поглощена» этим вентилем, и таким образом будет предотвращен вывод из программы ошибочного результата. То же самое произойдет и в вентиле Т, но второй вентиль F формирует величину 2, которая переведет в состояние готовности расположенный под этим вентилем смеситель. Указанный смеситель в свою очередь перешлет величину 2 на смеситель, находящийся вверху слева. Обратите внимание на то, как работает «арифметический раздел» программы. Отказавшись от описания программы как совокупности процедур и изобразив ее графически, мы сумели отобразить тот факт, что оба арифметических выражения, определенных в операторе IF, могут вычисляться параллельно с вычислением значения отношения оператора IF (Y>1). Описываемые действия завершаются работой вентилей Т и F, осуществляющих выбор нужного вычисленного выражения с целью его передачи в качестве исходной величины для нового шага итерации.
Рис. 22.9 показывает состояние программы в один из после дующих моментов (третий «мгновенный снимок»). Величина 2 будет возвращена в результате нового повторения циклического процесса в левой части графа. Таким образом, действие программы будет аналогично предыдущему, только изменятся значения токенов данных. Во время этого выполнения упомянутой циклического процесса на выходную линию программы никакие данные помещены не будут. Однако при этом блок принятия решения по критерию «первый операнд отношения больше второго» формирует на выходе значение TRUE, что дает возможность входным данным вентиля Т пройти на его выход и далее, в верхнюю часть графа.
Рис. 22.10 иллюстрирует более позднее состояние программы (четвертый «мгновенный снимок»). В этот момент на выходе блока принятия решения по критерию «первый операнд отношения меньше или равен второму» формируется управляющий токен FALSE, рассылаемый четырем адресатам (точкам) программы. На рис. 22.11 показано соответствующее состояние программы в этот момент времени: на входах вентиля F, расположенного в середине графа, сейчас имеются соответственно управляющий токен FALSE и токен данных, значение которого равно 4; в результате на выходной линии программы появится величина 4. Немаловажно также проследить продвижение потока остальных токенов по графу программы, поскольку программы потоков данных имеют одно
Рис.22.10. Состояние программы в момент Г.
Рис.22.11. Состояние программы в момент Д.
любопытное свойство: их блоки могут все еще пребывать в состоянии готовности к выполнению нению соответствующих функций даже после того, как программа сформировала требуемый результат. Вентиль F, расположенный в левой нижней части, уничтожит оба своих входных сигнала, вентиль Т пропустит величину 16, которая пройдет через смеситель в верхнюю часть графа, где дальнейшее продвижение этой величины будет заблокировано, поскольку на вход соответствующего смесителя подается управляющий токен ЛОЖНО. Таким же образом окажутся заблокированными величины 2 и 4, поступающие соответственно на правый и средний смесители.
Следовательно, вскоре после формирования на выходе результата программа прекращает функционирование, хотя и не произошло ее восстановление в нужное начальное состояние, показанное на рис. 22.6. (Граф содержит лишние токены данных, которых не было вначале.) Это является недостатком программы, поскольку упомянутые «застрявшие» токены будут препятствовать последующим попыткам выполнения этой программы. Можно было бы сделать так, чтобы программа сама уничтожала такие токены, но для упрощения проводимых рассуждений эти вопросы здесь не рассматриваются.
Подведем итог тому, что дает такое представление программы. Оно позволяет достичь высокой степени параллелизма выполнения операций, хотя с точки зрения программиста это не является основной целью программирования. Даже в такой весьма примитивной программе в каждый момент времени находилось несколько блоков, одновременно готовых к работе. Если предположить реализуемость подобного параллелизма в архитектуре вычислительной машины, то можно утверждать, что достижима высокая степень распараллеливания вычислений да же в небольших программах. Основа такой архитектуры рассматривается в следующем разделе.