При поэтапной обработке получение очередных данных может выполняться асинхронно разными серверами и в разных БД. Этапы обработки данных можно наглядно отобразить блок-схемой модулей обменивающихся данными через порты ввода/вывода.
Ранее (см. http://proza.ru/2024/10/08/1488) сделан вывод, что "готовность исходных данных должна инициировать и получение результатов", т.е должно выполняться управление по данным (Dataflow). В начале 80-х годов были эксперименты (на Западе) создания Dataflow машин, в которых поток данных состоял практически из операндов машинных команд. Однако такие архитектуры оказались неэффективными и к тому же использовали дорогую и медленную ассоциативную память. Поэтому перешли к "крупнозернистым" моделям, где каждый модуль обработки данных представлял собой блок операторов.
Наглядно "крупнозернистая" модель отображается блок-схемой алгоритма программы. Понятно, что алгоритм, исполняемый в каждом блоке, тоже может быть представлен блок-схемой из модулей, выполняющих части алгоритма блока. И т.д., вплоть до машинных команд. См. первый рисунок.
Каждый блок (или модуль) программы выполняет некоторую группу связанных операций над входными данными получая содержательный результат, который используется на следующих этапах обработки в других блоках. Когда данные переданы для обработки в следующие блоки, первые готовы обрабатывать очередную порцию данных.
Излагаемое в данной статье не является описанием мировых трендов в принципах потоковой обработки, а отражает исключительно авторскую концепцию.
Архитектура мультикомпьютерного комплекса (МКК) выбранная по критериям простоты и дешевизны показана на втором рисунке. Примерно так должны были выглядеть мультипроцессорные системы (контроллеры) разрабатываемые в конце 80-х в филиале Московского института электронных управляющих машин (ИНЭУМ АН СССР) вплоть до ликвидации филиала вместе со всеми проектами и разработками в процессе горбачёвской "перестройки".
Поскольку данные находятся в основном в портах, в том числе портах модулей блок-схем внутри блоков, и иногда в очередях, то особо большой локальной памяти процессорам не потребуется.
Основные же массивы данных должны храниться в унифицированных базах данных. Оптимально, если базы данных будут выполнены как специализированные устройства с идентичным интерфейсом управления и доступом к данным – независимо от структуры и связей конкретных данных. И вот только в этих устройствах для хранения выборок из БД может понадобиться многогигабайтная оперативная и многотерабайтная постоянная память.
Кстати, при наличии спецустройства с унифицированной БД, в которой (в метаданных) хранятся также и программы модулей обрабатывающих затребованные данные, отпадает необходимость в использовании привычных файловых систем и привычной же необходимости инсталляции программ.
Исходные данные поступают на входные порты блока, а результаты помещаются в выходные порты (на схеме изображены кружочками). Не связанные на приведенном фрагменте блок-схемы (рис.1), т.е. свободные, порты отмечены жёлтым цветом.
Назовём исполняемый модулем алгоритм функцией, а данное, помещаемое ею в порт, назовём возвращаемым значением функции. В результате получим программу, где функции связаны друг с другом через возвращаемые значения, так что присваивать переменным какие-либо промежуточные значения для временного хранения нет необходимости.
Полагаю, что вышеописанная модель соединения и работы модулей блок-схемы вполне соответствует концепции функциональных языков программирования. Однако в случае блок-схем целесообразно не ограничиться только одним возвращаемым значением.
Поскольку процесс вычисления управляется передачей данных от блока к блоку, то совершенно не играет роли порядок, в котором будут описаны алгоритмы каждого блока. Существенным является только описание связей выходных и входных портов блоков – от какого и какому передаются данные. Следовательно, язык программы описывающей соединение модулей блок-схем будет декларативным, а не императивным, когда важен порядок исполнения операторов.
Очевидно, что если данное отсутствует в каком-либо входном порту, или не взято в обработку следующими блоками из какого-либо выходного порта, то программа в данном блоке не может начать или завершить работу и должна ждать изменения ситуации. Возникает опасность, что процесс остановится.
Мною был разработан протокол движения данных (ПДД) кардинально устраняющий эти проблемы.
При управлении по данным, работа программных модулей управляется "протоколом движения данных" (ПДД), а не операционной системой, которая управляет процессами и совсем не нужна, даже для управления ресурсами. Все её функции могут выполняться сервисами при компиляции и загрузке программы, обращения к которым вставлены в её текст, и работа которых по мере востребования тоже управляется ПДД. Разделение и оккупация внешних устройств осуществляется началом и завершением транзакций <процесс, данные в котором не могут быть изменены, пока получателю не передан весь пакет>.
Данные между вычислительными модулями передаются по шинам данных. Аппаратные порты используются для обмена данными между ВМ по шинам данных и, возможно иногда, также между программными модулями в одном ВМ. При управлении по данным не важен их источник, так что любая из шин данных может быть "продолжена" любым подходящим устройством связи к другим МКК и иным устройствам.
Перед началом пересылки данных шину следует "захватить", чтобы не было взаимных помех. Обычно захват выполняется методом "взвешивания" адресов устройств, когда право передачи получает тот из претендентов, чей адрес на шине наименьший, но этот процесс занимает как минимум столько тактов, какова разрядность адресов.
Мною были разработаны принципы захвата шины за один такт независимо от числа устройств на ней. Но на современных технологиях, полагаю, это же можно осуществить и более изящными способами. В МКК целесообразно использовать "магистраль" состоящую из множества шин данных и запрос на захват посылать одновременно на все свободные в данный момент.
Сервис ПДД запускает программу модуля, если в его входном порту появилось данное. Результат исполнения программы помещается в его выходной порт и одновременно инициируется работа сервиса ПДД, который по шине данных выставляет "заявку" на передачу в связанный с ним (например, с таким же идентификационным номером) входной порт очередного модуля в другом ВМ.
Появление "заявки" инициирует в работу уже местный сервис ПДД, который принимает и размещает в памяти пересылаемый массив данных, а его адрес заносит во входной порт модуля, либо в очередь, если порт занят. Затем в этом ВМ возобновляется исполнение ожидающей обмена данными программы. Если создание очереди не предусмотрено и входной порт занят, то данное просто остаётся в выходном порту вычислившего его модуля.
Каждый порт имеет флаг Ф или семафор отмечающий наличие в нём данных, и остающийся взведённым, пока данные не будут переданы всем зарегистрированным клиентам.
Пусть Д - данное, Д=1 -есть готовые данные, Д=0 -нужны данные.
Обозначения: = сравнить, := установить или присвоить. Пусть М - программа модуля или блока, тогда М:=1 -запуск и продолжение работы М, М:=0 -приостановка исполнения программы.
П1 -входной порт, П2 -выходной порт, а Ф1 или Ф2 -флаги соответствующего порта. Ф=1 -флаг взведён – в порту есть данные, Ф:=0 -флаг сбрасывается, Ф:=1 -взводится.
Д:=П1 -данные забираются из порта, П2:=Д -данные помещаются в порт.
свП, свФ - связанные порты следующего модуля. свП1:=П2 -это передача данных.
Алгоритм передачи данных в выходной порт П2 и связанный входной свП1 показан на рис.3.
1.свП1 и П2 свободны. Данные из программы пересылаются сразу в свП1.
2.свП1 свободен, а П2 занят. Данные из П2 пересылаются в свП1, а данные из программы в П2.
3. свП1занят, а П2 свободен. Данные из программы засылаются в П2.
4. свП1 и П2 заняты.
В пп.3 и 4 инициируется исполнение программы в связанном модуле.
Алгоритм приёма данных из входного порта П1 и связанного выходного свП2 показан на рис.4.
Цифры в рамках - это метки. О метках см. в конце http://proza.ru/2024/10/15/912
1.В П1 есть данные, а в свП2 нет. Данные забираются из П1.
2.Данные есть в П1 и свП2. Данные забираются из П1, а затем в П1 пересылаются данные из свП2.
3.Данные есть только в свП2. Они сразу из него забираются минуя порт П1.
4.Данных в портах нет.
В пп.3 и 4 инициируется исполнение программы в связанном модуле.
Собственно Ноу-хау заключается в анализе состояния связанных портов и инициации работы программы в связанном модуле (на блок-схемах инициация обозначена выражением свМ:=1), если нет входных данных или не забираются выходные. Этот алгоритм позволит избежать дедлоков (deadlock, "смертельные объятия"), так как исключена стратегия взаимного ожидания появления нужных ресурсов.
Поэтому управляемую по данным программу можно запускать с любого блока, например с самого последнего формирующего итоговые данные. Благодаря инициации будут активированы все предшествующие участвующие блоки, вплоть до самого первого получающего исходные данные.
В принципе, сервис ПДД можно дооснастить сервисом распараллеливания, подгружающим в свободные или малонагруженные ВМ копии программных блоков, во входных портах которых создаются очереди. При оптимальном распараллеливании блоков по ВМ должен получиться конвейер вычислений, когда темп получения кадров результатов на выходе будет успевать за темпом поступления кадров на вход конвейера и очередей не образуется.