Введение
Цепочка обработки данных
In computing, a pipeline, also known as a data pipeline, is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time sliced fashion. Some amount of buffer storage is often inserted between elements. Computer related pipelines include:
Instruction pipelines, such as the classic RISC pipeline, which are used in central processing units (CPUs) and other microprocessors to allow overlapping execution of multiple instructions with the same circuitry. The circuitry is usually divided up into stages and each stage processes a specific part of one instruction at a time, passing the partial results to the next stage. Examples of stages are instruction decode, arithmetic/logic and register fetch. They are related to the technologies of superscalar execution, operand forwarding, speculative execution and out of order execution. Graphics pipelines, found in most graphics processing units (GPUs), which consist of multiple arithmetic units, or complete CPUs, that implement the various stages of common rendering operations (perspective projection, window clipping, color and light calculation, rendering, etc.). Software pipelines, which consist of a sequence of computing processes (commands, program runs, tasks, threads, procedures, etc. ), conceptually executed in parallel, with the output stream of one process being automatically fed as the input stream of the next one. The Unix system call pipe is a classic example of this concept. HTTP pipelining, the technique of issuing multiple HTTP requests through the same TCP connection, without waiting for the previous one to finish before issuing a new one. Some operating systems may provide UNIX like syntax to string several program runs in a pipeline, but implement the latter as simple serial execution, rather than true pipelining—namely, by waiting for each program to finish before starting the next one.
В вычислительной технике конвейер, также известный как конвейер данных, представляет собой набор элементов обработки данных, соединенных последовательно, где выход одного элемента является входом следующего. Элементы конвейера часто выполняются параллельно или с разделением по времени. Между элементами часто вставляется некоторый объем буферной памяти. Компьютерные конвейеры включают в себя:
In computing, a pipeline, also known as a data pipeline, is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time sliced fashion. Some amount of buffer storage is often inserted between elements. Computer related pipelines include:
Instruction pipelines, such as the classic RISC pipeline, which are used in central processing units (CPUs) and other microprocessors to allow overlapping execution of multiple instructions with the same circuitry. The circuitry is usually divided up into stages and each stage processes a specific part of one instruction at a time, passing the partial results to the next stage. Examples of stages are instruction decode, arithmetic/logic and register fetch. They are related to the technologies of superscalar execution, operand forwarding, speculative execution and out of order execution. Graphics pipelines, found in most graphics processing units (GPUs), which consist of multiple arithmetic units, or complete CPUs, that implement the various stages of common rendering operations (perspective projection, window clipping, color and light calculation, rendering, etc.). Software pipelines, which consist of a sequence of computing processes (commands, program runs, tasks, threads, procedures, etc. ), conceptually executed in parallel, with the output stream of one process being automatically fed as the input stream of the next one. The Unix system call pipe is a classic example of this concept. HTTP pipelining, the technique of issuing multiple HTTP requests through the same TCP connection, without waiting for the previous one to finish before issuing a new one. Some operating systems may provide UNIX like syntax to string several program runs in a pipeline, but implement the latter as simple serial execution, rather than true pipelining—namely, by waiting for each program to finish before starting the next one.
Конвейеры инструкций, такие как классический конвейер RISC, которые используются в центральных процессорах (CPU) и других микропроцессорах для обеспечения перекрывающегося выполнения нескольких инструкций с использованием одной и той же схемы. Схема обычно разделена на этапы, и каждый этап обрабатывает определенную часть одной инструкции за раз, передавая частичные результаты на следующий этап. Примеры этапов: декодирование инструкций, арифметические/логические операции и выборка из регистров. Они связаны с технологиями суперскалярного исполнения, пересылки операндов, спекулятивного исполнения и исполнения вне порядка.
In computing, a pipeline, also known as a data pipeline, is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time sliced fashion. Some amount of buffer storage is often inserted between elements. Computer related pipelines include:
Instruction pipelines, such as the classic RISC pipeline, which are used in central processing units (CPUs) and other microprocessors to allow overlapping execution of multiple instructions with the same circuitry. The circuitry is usually divided up into stages and each stage processes a specific part of one instruction at a time, passing the partial results to the next stage. Examples of stages are instruction decode, arithmetic/logic and register fetch. They are related to the technologies of superscalar execution, operand forwarding, speculative execution and out of order execution. Graphics pipelines, found in most graphics processing units (GPUs), which consist of multiple arithmetic units, or complete CPUs, that implement the various stages of common rendering operations (perspective projection, window clipping, color and light calculation, rendering, etc.). Software pipelines, which consist of a sequence of computing processes (commands, program runs, tasks, threads, procedures, etc. ), conceptually executed in parallel, with the output stream of one process being automatically fed as the input stream of the next one. The Unix system call pipe is a classic example of this concept. HTTP pipelining, the technique of issuing multiple HTTP requests through the same TCP connection, without waiting for the previous one to finish before issuing a new one. Some operating systems may provide UNIX like syntax to string several program runs in a pipeline, but implement the latter as simple serial execution, rather than true pipelining—namely, by waiting for each program to finish before starting the next one.
Графические конвейеры, которые можно найти в большинстве графических процессоров (GPU), состоящие из нескольких арифметических устройств или полноценных процессоров, реализующих различные этапы обычных операций рендеринга (перспективная проекция, отсечение, вычисление цвета и освещения, рендеринг и т. д.).
In computing, a pipeline, also known as a data pipeline, is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time sliced fashion. Some amount of buffer storage is often inserted between elements. Computer related pipelines include:
Instruction pipelines, such as the classic RISC pipeline, which are used in central processing units (CPUs) and other microprocessors to allow overlapping execution of multiple instructions with the same circuitry. The circuitry is usually divided up into stages and each stage processes a specific part of one instruction at a time, passing the partial results to the next stage. Examples of stages are instruction decode, arithmetic/logic and register fetch. They are related to the technologies of superscalar execution, operand forwarding, speculative execution and out of order execution. Graphics pipelines, found in most graphics processing units (GPUs), which consist of multiple arithmetic units, or complete CPUs, that implement the various stages of common rendering operations (perspective projection, window clipping, color and light calculation, rendering, etc.). Software pipelines, which consist of a sequence of computing processes (commands, program runs, tasks, threads, procedures, etc. ), conceptually executed in parallel, with the output stream of one process being automatically fed as the input stream of the next one. The Unix system call pipe is a classic example of this concept. HTTP pipelining, the technique of issuing multiple HTTP requests through the same TCP connection, without waiting for the previous one to finish before issuing a new one. Some operating systems may provide UNIX like syntax to string several program runs in a pipeline, but implement the latter as simple serial execution, rather than true pipelining—namely, by waiting for each program to finish before starting the next one.
Программные конвейеры, состоящие из последовательности вычислительных процессов (команд, запусков программ, задач, потоков, процедур и т. д.), концептуально выполняемых параллельно, при этом выходной поток одного процесса автоматически подается в качестве входного потока следующего. Системный вызов pipe в Unix является классическим примером этой концепции.
In computing, a pipeline, also known as a data pipeline, is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time sliced fashion. Some amount of buffer storage is often inserted between elements. Computer related pipelines include:
Instruction pipelines, such as the classic RISC pipeline, which are used in central processing units (CPUs) and other microprocessors to allow overlapping execution of multiple instructions with the same circuitry. The circuitry is usually divided up into stages and each stage processes a specific part of one instruction at a time, passing the partial results to the next stage. Examples of stages are instruction decode, arithmetic/logic and register fetch. They are related to the technologies of superscalar execution, operand forwarding, speculative execution and out of order execution. Graphics pipelines, found in most graphics processing units (GPUs), which consist of multiple arithmetic units, or complete CPUs, that implement the various stages of common rendering operations (perspective projection, window clipping, color and light calculation, rendering, etc.). Software pipelines, which consist of a sequence of computing processes (commands, program runs, tasks, threads, procedures, etc. ), conceptually executed in parallel, with the output stream of one process being automatically fed as the input stream of the next one. The Unix system call pipe is a classic example of this concept. HTTP pipelining, the technique of issuing multiple HTTP requests through the same TCP connection, without waiting for the previous one to finish before issuing a new one. Some operating systems may provide UNIX like syntax to string several program runs in a pipeline, but implement the latter as simple serial execution, rather than true pipelining—namely, by waiting for each program to finish before starting the next one.
HTTP-пиплайнинг – техника отправки нескольких HTTP-запросов через одно и то же TCP-соединение, без ожидания завершения предыдущего запроса перед отправкой нового. Некоторые операционные системы могут предоставлять синтаксис, подобный UNIX, для объединения нескольких запусков программ в конвейер, но реализовывать его как простое последовательное выполнение, а не истинный конвейерный режим – то есть, ожидая завершения каждой программы перед запуском следующей.
In computing, a pipeline, also known as a data pipeline, is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time sliced fashion. Some amount of buffer storage is often inserted between elements. Computer related pipelines include:
Instruction pipelines, such as the classic RISC pipeline, which are used in central processing units (CPUs) and other microprocessors to allow overlapping execution of multiple instructions with the same circuitry. The circuitry is usually divided up into stages and each stage processes a specific part of one instruction at a time, passing the partial results to the next stage. Examples of stages are instruction decode, arithmetic/logic and register fetch. They are related to the technologies of superscalar execution, operand forwarding, speculative execution and out of order execution. Graphics pipelines, found in most graphics processing units (GPUs), which consist of multiple arithmetic units, or complete CPUs, that implement the various stages of common rendering operations (perspective projection, window clipping, color and light calculation, rendering, etc.). Software pipelines, which consist of a sequence of computing processes (commands, program runs, tasks, threads, procedures, etc. ), conceptually executed in parallel, with the output stream of one process being automatically fed as the input stream of the next one. The Unix system call pipe is a classic example of this concept. HTTP pipelining, the technique of issuing multiple HTTP requests through the same TCP connection, without waiting for the previous one to finish before issuing a new one. Some operating systems may provide UNIX like syntax to string several program runs in a pipeline, but implement the latter as simple serial execution, rather than true pipelining—namely, by waiting for each program to finish before starting the next one.
Концепция и мотивация
Трубопровод – это концепция, широко используемая в повседневной жизни. Например, на конвейере автомобильного завода каждая конкретная задача – такая как установка двигателя, установка капота и установка колес – часто выполняется отдельной рабочей станцией. Станции выполняют свои задачи параллельно, каждая на отдельном автомобиле. Как только для автомобиля выполнена одна задача, он перемещается на следующую станцию. Изменения во времени, необходимом для выполнения задач, могут быть компенсированы "буферизацией" (удержанием одного или нескольких автомобилей в пространстве между станциями) и/или "остановкой" (временной остановкой предыдущих станций), пока следующая станция не станет свободной. Предположим, что для сборки одного автомобиля требуется три задачи, занимающие соответственно 20, 10 и 15 минут. Если бы все три задачи выполняла одна станция, завод выпускал бы один автомобиль каждые 45 минут. Используя конвейер из трех станций, завод выпустил бы первый автомобиль через 45 минут, а затем новый каждые 20 минут. Как показывает этот пример, конвейер не уменьшает задержку, то есть общее время, необходимое для прохождения одного элемента через всю систему. Однако он увеличивает пропускную способность системы, то есть скорость обработки новых элементов после первого.
Балансирование этапов
Поскольку пропускная способность конвейера не может быть выше, чем у его самого медленного звена, разработчику следует стремиться к такому распределению работы и ресурсов между этапами, чтобы все они выполняли свои задачи за одинаковое время. В примере со сборкой автомобиля, если бы каждая из трех задач занимала 15 минут вместо 20, 10 и 15 минут, задержка осталась бы прежней – 45 минут, но новый автомобиль завершался бы каждые 15 минут, а не 20.
Буферная система
В идеальных условиях, если все обрабатывающие элементы синхронизированы и требуют одинакового времени для обработки, то каждый элемент может получать данные сразу после их выдачи предыдущим элементом, за один тактовый цикл. Таким образом, данные будут проходить по конвейеру с постоянной скоростью, подобно волнам в водном канале. В таких "волновых конвейерах" не требуется синхронизация или буферизация между этапами, кроме необходимой памяти для хранения данных. В более общем случае, буферизация между этапами конвейера необходима, когда время обработки нерегулярно или когда элементы могут создаваться или удаляться в процессе обработки. Например, в графическом конвейере, обрабатывающем треугольники для отображения на экране, элемент, проверяющий видимость каждого треугольника, может отбрасывать невидимые треугольники или генерировать два или более треугольных фрагмента, если они частично скрыты. Буферизация также необходима для компенсации неравномерности скорости, с которой приложение передает данные на первый этап и потребляет результаты с последнего. Буфер между двумя этапами может быть реализован как простой аппаратный регистр с соответствующей логикой синхронизации и сигнализации. Когда этап А сохраняет данные в регистре, он отправляет сигнал "данные доступны" следующему этапу B. После использования данных, B отправляет сигнал "данные получены" этапу A. Этап А приостанавливается, ожидая этот сигнал, прежде чем сохранять следующие данные в регистре. Этап B приостанавливается, ожидая сигнала "данные доступны", если он готов к обработке следующего элемента, но этап A еще не предоставил его. Если время обработки элемента переменное, весь конвейер может часто останавливаться, ожидая, пока этот элемент и все предыдущие обработают данные в своих входных буферах. Частоту таких остановок можно снизить, предоставив в буфере ввода этапа место для нескольких элементов. Такой буфер с несколькими элементами обычно реализуется в виде очереди FIFO (первый пришел – первый ушел). Предыдущий этап все еще может быть остановлен при заполнении очереди, но частота таких событий уменьшится с увеличением количества слотов буфера. Теория очередей позволяет определить необходимое количество слотов буфера в зависимости от изменчивости времени обработки и требуемой производительности.
Нелинейные трубопроводы
Если какой-то этап занимает (или может занимать) значительно больше времени, чем остальные, и его нельзя ускорить, разработчик может использовать два или более вычислительных элемента для параллельного выполнения этой задачи, с одним общим входным буфером и одним общим выходным буфером. Каждый элемент, завершив обработку текущего элемента данных, помещает его в общий выходной буфер и берет следующий элемент данных из общего входного буфера. Эта концепция "нелинейного" или "динамического" конвейера иллюстрируется магазинами или банками, где два или более кассира обслуживают клиентов из одной очереди ожидания.
Зависимости между позициями
В некоторых случаях обработка элемента Y на этапе А может зависеть от результатов или эффекта обработки предыдущего элемента X на какой-либо более поздней стадии B конвейера. В этом случае этап А не может правильно обработать элемент Y, пока элемент X не завершит обработку на этапе B. Эта ситуация очень часто встречается в конвейерах команд. Например, предположим, что Y — это арифметическая инструкция, которая считывает содержимое регистра, который, как предполагалось, был изменен более ранней инструкцией X. Пусть A будет этапом, который извлекает операнды инструкции, а B — этапом, который записывает результат в указанный регистр. Если этап А пытается обработать инструкцию Y до того, как инструкция X достигнет этапа B, регистр может все еще содержать старое значение, и результат Y будет некорректным. Для правильной обработки таких конфликтов конвейер должен быть оснащен дополнительными схемами или логикой, которые обнаруживают их и принимают соответствующие меры. Стратегии для этого включают:
Задержка: Каждый затронутый этап, такой как A, останавливается до тех пор, пока зависимость не будет устранена, то есть до тех пор, пока не будет доступна необходимая информация и/или не будет достигнуто требуемое состояние. Переупорядочение элементов: вместо задержки этап А может отложить элемент Y и искать любой последующий элемент Z во входном потоке, который не имеет никаких зависимостей от предыдущих элементов. В конвейерах команд эта техника называется внеочередным выполнением. Предсказание и откат: одним из важных примеров зависимости между элементами является обработка условного перехода инструкции X конвейером команд. Первая стадия A конвейера, которая извлекает следующую инструкцию Y для выполнения, не может выполнить свою задачу, пока X не извлечет свой операнд и не определит, следует ли выполнять переход или нет. Это может занять много тактов, поскольку операнд X может, в свою очередь, зависеть от предыдущих инструкций, которые извлекают данные из основной памяти. Вместо того чтобы останавливаться в ожидании завершения X, этап А может предсказать, будет ли выполнен переход, и извлечь следующую инструкцию Y на основе этого предсказания. Если предсказание окажется неверным (что, будем надеяться, произойдет редко), системе придется откатиться и возобновить работу с правильным выбором. А именно, все изменения, внесенные в состояние машины на этапе А и последующих этапах на основе этого предсказания, должны быть отменены, инструкции, следующие за X, уже находящиеся в конвейере, должны быть сброшены, и этап А должен перезапуститься с правильным указателем инструкции. Эта стратегия предсказания переходов является частным случаем спекулятивного выполнения.
Stalling: Every affected stage, such as A, is halted until the dependency is resolved—that is, until the required information is available and/or the required state has been achieved. Reordering items: Instead of stalling, stage A may put item Y aside and look for any subsequent item Z in its input stream that does not have any dependencies pending with any earlier item. In instruction pipelines, this technique is called out of order execution. Guess and backtrack: One important example of item to item dependency is the handling of a conditional branch instruction X by an instruction pipeline. The first stage A of the pipeline, that fetches the next instruction Y to be executed, cannot perform its task until X has fetched its operand and determined whether the branch is to be taken or not. That may take many clock cycles, since the operand of X may in turn depend on previous instructions that fetch data from main memory. Rather than halt while waiting for X to be finished, stage A may guess whether the branch will be taken or not, and fetch the next instruction Y based on that guess. If the guess later turns out to be incorrect (hopefully rarely), the system would have to backtrack and resume with the correct choice. Namely, all the changes that were made to the machine's state by stage A and subsequent stages based on that guess would have to be undone, the instructions following X already in the pipeline would have to be flushed, and stage A would have to restart with the correct instruction pointer. This branch prediction strategy is a special case of speculative execution.
Типичные реализации программного обеспечения
Для эффективной реализации конвейеров данных необходима стратегия планирования задач ЦП для распределения работы между доступными ядрами процессора, а также использование структур данных, с которыми будут оперировать этапы конвейера. Например, производные UNIX могут конвейеризировать команды, соединяющие стандартный ввод-вывод различных процессов, используя каналы, реализованные операционной системой. Подходы нижнего уровня могут полагаться на потоки, предоставляемые операционной системой, для планирования работы на этапах: жизнеспособны и существуют как реализации на основе пула потоков, так и реализации с одним потоком на этап. Существуют и другие стратегии, основанные на кооперативной многозадачности, которые не требуют нескольких потоков выполнения и, следовательно, дополнительных ядер ЦП, например, использование циклического планировщика с фреймворком на основе корутин. В этом контексте каждый этап может быть реализован с собственной корутиной, передавая управление обратно планировщику после завершения своей задачи. Такой подход может потребовать тщательного контроля над этапами конвейера, чтобы избежать превышения выделенного времени.
Затраты и недостатки
Система с конвейерной обработкой обычно требует больше ресурсов (схемные элементы, процессорные устройства, компьютерная память и т. д.), чем система, выполняющая обработку по одному блоку за раз, поскольку её этапы не могут совместно использовать эти ресурсы, а также из-за необходимости буферизации и дополнительной логики синхронизации между элементами. Более того, передача данных между отдельными процессорными элементами может увеличить задержку, особенно в длинных конвейерах. Дополнительная сложность, связанная с конвейерной обработкой, может быть значительной, если существуют зависимости между обработкой различных элементов, особенно при использовании стратегии предсказания и отката для их обработки. Фактически, стоимость реализации такой стратегии для сложных наборов команд послужила стимулом для радикальных предложений по упрощению компьютерной архитектуры, таких как RISC и VLIW. Компиляторы также были нагружены задачей перестановки машинных инструкций для повышения эффективности работы конвейера команд.
Новые технологии
Это правда, что в последние годы требования к приложениям и их базовому оборудованию значительно возросли. Например, создание конвейеров с приложениями, обрабатывающими данные построчно на одном узле, больше не представляется возможным из-за объема и разнообразия больших данных. Однако с появлением движков для анализа данных, таких как Hadoop или, более недавно, Apache Spark, стало возможным распределять большие наборы данных между множеством вычислительных узлов, что позволило приложениям достичь эффективности, в несколько сотен раз превышающей прежние возможности. В результате, сегодня даже компьютер среднего уровня, использующий распределенные вычисления, способен создавать и запускать конвейеры обработки больших данных.