Введение
Парадигма программирования для параллельной обработки потоков данных. В информатике, обработка потоков (также известная как обработка потоков событий, обработка потоков данных или распределённая обработка потоков) — это парадигма программирования, рассматривающая потоки, или последовательности событий во времени, как центральные входные и выходные объекты вычислений. Обработка потоков охватывает программирование потоков данных, реактивное программирование и распределённую обработку данных. Системы обработки потоков стремятся обеспечить параллельную обработку данных в потоках и используют потоковые алгоритмы для эффективной реализации. Программный стек для этих систем включает в себя такие компоненты, как модели программирования и языки запросов для представления вычислений; системы управления потоками для распределения и планирования; и аппаратные компоненты для ускорения, включая блоки с плавающей запятой, графические процессоры и программируемые вентильные матрицы. Парадигма потоковой обработки упрощает параллельное программное и аппаратное обеспечение, ограничивая возможности параллельных вычислений. Для последовательности данных (потока) к каждому элементу потока применяется ряд операций (ядерные функции). Ядерные функции обычно объединяются в конвейер, и предпринимаются попытки оптимального повторного использования локальной памяти на чипе, чтобы минимизировать потери пропускной способности, связанные с взаимодействием с внешней памятью. Типичным является однородный поток, когда одна ядерная функция применяется ко всем элементам потока. Поскольку абстракции ядра и потока выявляют зависимости данных, инструменты компилятора могут полностью автоматизировать и оптимизировать задачи управления чипом. Аппаратное обеспечение для обработки потоков может использовать, например, таблицу результатов (scoreboard) для инициирования прямого доступа к памяти (DMA) при установлении зависимостей. Исключение ручного управления DMA снижает сложность программного обеспечения, а связанное с этим исключение аппаратного кэширования ввода-вывода уменьшает область данных, вовлекаемую в обслуживание специализированными вычислительными блоками, такими как арифметико-логические устройства. В 1980-х годах обработка потоков изучалась в контексте программирования потоков данных. Примером является язык SISAL (Streams and Iteration in a Single Assignment Language).
In computer science, stream processing (also known as event stream processing, data stream processing, or distributed stream processing) is a programming paradigm which views streams, or sequences of events in time, as the central input and output objects of computation. Stream processing encompasses dataflow programming, reactive programming, and distributed data processing. Stream processing systems aim to expose parallel processing for data streams and rely on streaming algorithms for efficient implementation. The software stack for these systems includes components such as programming models and query languages, for expressing computation; stream management systems, for distribution and scheduling; and hardware components for acceleration including floating point units, graphics processing units, and field programmable gate arrays. The stream processing paradigm simplifies parallel software and hardware by restricting the parallel computation that can be performed. Given a sequence of data (a stream), a series of operations (kernel functions) is applied to each element in the stream. Kernel functions are usually pipelined, and optimal local on chip memory reuse is attempted, in order to minimize the loss in bandwidth, associated with external memory interaction. Uniform streaming, where one kernel function is applied to all elements in the stream, is typical. Since the kernel and stream abstractions expose data dependencies, compiler tools can fully automate and optimize on chip management tasks. Stream processing hardware can use scoreboarding, for example, to initiate a direct memory access (DMA) when dependencies become known. The elimination of manual DMA management reduces software complexity, and an associated elimination for hardware cached I/O, reduces the data area expanse that has to be involved with service by specialized computational units such as arithmetic logic units. During the 1980s stream processing was explored within dataflow programming. An example is the language SISAL (Streams and Iteration in a Single Assignment Language).
Сравнение с предыдущими параллельными парадигмами
Основные компьютеры начинали с парадигмы последовательного выполнения. Традиционные процессоры основаны на архитектуре SISD, что означает, что они концептуально выполняют только одну операцию за раз. По мере эволюции вычислительных потребностей в мире объём управляемых данных очень быстро рос. Стало очевидно, что модель последовательного программирования не справлялась с возросшей потребностью в вычислительной мощности. Были предприняты различные попытки найти альтернативные способы выполнения огромного количества вычислений, но единственным решением оказалось использование некоторого уровня параллельного выполнения. Результатом этих усилий стала SIMD – парадигма программирования, позволяющая применять одну инструкцию к множеству экземпляров (разных) данных. SIMD чаще всего использовался в среде SWAR. Применение более сложных структур позволяло реализовать также параллелизм MIMD. Несмотря на эффективность этих двух парадигм, их практическая реализация сталкивалась с ограничениями, начиная от проблем выравнивания памяти и заканчивая проблемами синхронизации и ограниченным уровнем параллелизма. Лишь немногие SIMD-процессоры сохранились как отдельные компоненты; большинство были интегрированы в стандартные процессоры. Рассмотрим простую программу, складывающую два массива, каждый из которых содержит 100 4-компонентных векторов (то есть всего 400 чисел).
Исследования
Стэнфордский университет реализовывал проекты по потоковой обработке данных, включая Стэнфордский проект программируемого затенения в реальном времени, начатый в 1999 году. В 2002 году был разработан прототип под названием Imagine. Проект Merrimac продолжался примерно до 2004 года. Компания AT&T также проводила исследования процессоров с расширенной потоковой обработкой, в то время как графические процессоры стремительно развивались в отношении скорости и функциональности. С тех пор было разработано множество языков потоковой обработки, а также специализированное аппаратное обеспечение.
Модели вычислений для обработки потоков
Помимо описания потоковых приложений на языках высокого уровня, модели вычислений (MoC) также широко применяются как модели потока данных и модели, основанные на процессах.
Общая архитектура процессора
Исторически сложилось так, что процессоры начали внедрять различные уровни оптимизации доступа к памяти из-за постоянно растущей производительности по сравнению с относительно медленно увеличивающейся пропускной способностью внешней памяти. По мере того как этот разрыв увеличивался, значительная площадь кристалла выделялась для маскировки задержек памяти. Поскольку получение информации и опкодов для этих немногих АЛУ обходится дорого, очень небольшая площадь кристалла отводится под фактические математические устройства (в качестве приблизительной оценки, можно считать, что это менее 10%). Схожая архитектура существует и в потоковых процессорах, но благодаря новой модели программирования количество транзисторов, выделенных на управление, на самом деле невелико. Если рассматривать всю систему в целом, потоковые процессоры обычно работают в контролируемой среде. Графические процессоры (GPU) существуют на платах расширения (кажется, это относится и к Imagine). Центральные процессоры (CPU) продолжают управлять системными ресурсами, запускать приложения и выполнять подобные задачи. Потоковый процессор обычно оснащен быстрой, эффективной, проприетарной шиной памяти (в настоящее время широко используются кроссбарные коммутаторы, в прошлом применялись многошинные системы). Точное количество линий памяти зависит от ценового сегмента. На момент написания этого текста все еще встречаются 64-битные соединения (начальный уровень). Большинство моделей среднего класса используют быструю 128-битную кроссбарную матрицу (с 4 или 2 сегментами), а высокопроизводительные модели развертывают огромные объемы памяти (фактически до 512 МБ) с немного более медленным кроссбаром шириной 256 бит. В отличие от них, стандартные процессоры от Intel Pentium до некоторых Athlon 64 имеют только одну 64-битную шину данных. Образцы доступа к памяти гораздо более предсказуемы. Хотя массивы и существуют, их размер фиксируется при вызове ядра. Наиболее близким аналогом многоуровневой косвенной адресации является цепочка косвенных адресов, которая, однако, гарантированно в конечном итоге будет читать или записывать данные из определенной области памяти (внутри потока). Благодаря SIMD-природе вычислительных блоков потокового процессора (кластеров АЛУ), операции чтения/записи, как ожидается, будут выполняться блоками, поэтому память оптимизирована для высокой пропускной способности, а не низкой задержки (в отличие, например, от Rambus и DDR SDRAM). Это также обеспечивает эффективное согласование по шине памяти. Большая часть (90%) работы потокового процессора выполняется на кристалле, требуя хранения в памяти только 1% глобальных данных. Здесь важно знание временных переменных и зависимостей ядра. Внутри потокового процессора реализованы различные схемы связи и управления, но особенно интересен файл регистров потока (SRF). Концептуально это большой кэш, в котором потоковые данные хранятся для последующей передачи во внешнюю память блоками. Как кэш, управляемый программным обеспечением, SRF совместно используется всеми кластерами АЛУ. Ключевая концепция и инновация, реализованная в чипе Imagine от Стэнфорда, заключается в том, что компилятор способен автоматизировать и выделять память оптимальным образом, полностью прозрачно для программиста. Зависимости между функциями ядра и данными известны благодаря модели программирования, что позволяет компилятору выполнять анализ потока управления и оптимально упаковывать SRF. Обычно кэширование и управление DMA могут занимать большую часть времени разработки проекта, что потоковый процессор (или, по крайней мере, Imagine) полностью автоматизирует. Тесты, проведенные в Стэнфорде, показали, что компилятор справляется с планированием памяти не хуже, а иногда и лучше, чем ручная настройка с большими усилиями. Есть доказательства того, что может быть много кластеров, поскольку межкластерное взаимодействие считается редким. Однако внутри каждого кластера можно эффективно использовать меньшее количество АЛУ, поскольку внутрикластерное взаимодействие является обычным и, следовательно, должно быть высокоэффективным. Чтобы обеспечить АЛУ данными, каждое АЛУ оснащено локальными файлами регистров (LRF), которые по сути являются его доступными регистрами. Эта трехступенчатая схема доступа к данным позволяет легко хранить временные данные вдали от медленной памяти, что делает кремниевую реализацию высокоэффективной и энергосберегающей.
Проблемы с оборудованием в цикле
Хотя можно разумно ожидать увеличения скорости в десять раз (даже от распространенных графических процессоров при вычислениях в потоковом режиме), не все приложения извлекают из этого выгоду. Основная проблема заключается в задержках связи. Несмотря на то, что PCI Express улучшил ситуацию благодаря полнодуплексной связи, настройка и запуск графического процессора (и, возможно, универсального потокового процессора) может занять значительное время. Это означает, что их использование для небольших наборов данных обычно неэффективно. Поскольку изменение ядра – довольно дорогая операция, потоковая архитектура также накладывает штрафы на небольшие потоки данных, явление, известное как эффект короткого потока. Конвейерная обработка – очень распространенная и широко используемая практика на потоковых процессорах, при этом графические процессоры имеют конвейеры, состоящие более чем из 200 этапов. Стоимость переключения настроек зависит от изменяемой настройки, но в настоящее время считается, что она всегда высока. Для решения этих проблем на различных уровнях конвейера были разработаны различные методы, такие как "убер-шейдеры" и "текстурные атласы". Эти методы ориентированы на игры из-за специфики графических процессоров, но концепции также представляют интерес для универсальной потоковой обработки.