В вычислении , A вектор процессор или массив процессора является центральный процессор (ЦП) , который реализует набор команд , где его инструкции по эксплуатации на одномерных массивов данных , называемых векторов . Это отличается от скалярных процессоров , инструкции которых работают только с отдельными элементами данных, и от тех же самых скалярных процессоров, имеющих арифметические блоки SIMD . Векторные процессоры могут значительно улучшить производительность при выполнении определенных рабочих нагрузок, особенно численного моделирования и аналогичных задач. Методы векторной обработки также работают воборудование игровой приставки и в графических ускорителях .
Векторные машины появились в начале 1970-х и доминировали в дизайне суперкомпьютеров с 1970-х по 1990-е годы, особенно на различных платформах Cray . Быстрое падение соотношения цены и производительности обычных микропроцессоров привело к упадку векторного суперкомпьютера в конце 1990-х годов.
История
Ранняя работа
Разработка векторной обработки началась в начале 1960-х годов в Westinghouse в их проекте «Соломон». Целью Соломона было резко повысить математическую производительность за счет использования большого количества простых математических сопроцессоров под управлением одного главного процессора . ЦП передал одну общую инструкцию всем арифметико-логическим устройствам (ALU), по одной на цикл, но с разными точками данных для каждого из них, над которыми нужно работать. Это позволило машине Соломона применить один алгоритм к большому набору данных , подаваемому в виде массива.
В 1962 году Westinghouse отменил проект, но его работа была возобновлена в Университете Иллинойса под названием ILLIAC IV . Их версия проекта изначально предусматривала установку 1 GFLOPS с 256 ALU, но, когда она была наконец поставлена в 1972 году, она имела только 64 ALU и могла достигать скорости только от 100 до 150 MFLOPS. Тем не менее, он показал, что основная концепция была правильной, и при использовании в приложениях с интенсивным использованием данных, таких как вычислительная гидродинамика , ILLIAC был самой быстрой машиной в мире. Подход ILLIAC с использованием отдельных ALU для каждого элемента данных не является общим для более поздних проектов и часто упоминается в отдельной категории - массово-параллельные вычисления.
Компьютер для операций с функциями был представлен и разработан Карцева в 1967 г. [1]
Суперкомпьютеры
Первое успешное внедрение векторной обработки произошло в 1966 году, когда были представлены Control Data Corporation STAR-100 и усовершенствованный научный компьютер Texas Instruments (ASC).
Базовый ASC (т. Е. «Однотрубный») ALU использует конвейерную архитектуру, которая поддерживает как скалярные, так и векторные вычисления, с максимальной производительностью, достигающей примерно 20 MFLOPS, что легко достигается при обработке длинных векторов. Расширенные конфигурации ALU поддерживали «два канала» или «четыре канала» с соответствующим увеличением производительности в 2 или 4 раза. Пропускной способности памяти было достаточно для поддержки этих расширенных режимов.
В остальном STAR-100 был медленнее, чем собственные суперкомпьютеры CDC, такие как CDC 7600 , но в задачах, связанных с данными, они могли не отставать, будучи намного меньшими и менее дорогими. Однако машине также потребовалось значительное время для декодирования векторных инструкций и подготовки к запуску процесса, поэтому требовались очень специфические наборы данных для работы, прежде чем она действительно ускорила что-либо.
Векторный метод был впервые полностью использован в 1976 году на знаменитом Cray-1 . Вместо того, чтобы оставлять данные в памяти, как в STAR-100 и ASC, в конструкции Cray было восемь векторных регистров , в каждом из которых содержалось по шестьдесят четыре 64-битных слова. Векторные инструкции применялись между регистрами, что намного быстрее, чем обращение к основной памяти. В то время как STAR-100 применяет одну операцию к длинному вектору в памяти, а затем переходит к следующей операции, дизайн Cray загружает меньшую часть вектора в регистры, а затем применяет к этим данным столько операций, сколько может. , тем самым избегая многих из гораздо более медленных операций доступа к памяти.
В дизайне Cray для реализации векторных инструкций использовался конвейерный параллелизм, а не несколько ALU. Кроме того, в проекте были полностью отдельные конвейеры для разных инструкций, например, сложение / вычитание было реализовано на другом оборудовании, чем умножение. Это позволило передать пакет векторных инструкций по конвейеру в каждый из субъединиц ALU, метод, который они назвали векторной цепочкой . Cray-1 обычно имел производительность около 80 MFLOPS, но при работе до трех цепей он мог достигать максимума 240 MFLOPS и в среднем около 150 MFLOPS - намного быстрее, чем любая машина того времени.
![](http://wikiimg.tojsiabtv.com/wikipedia/commons/thumb/9/9b/Cray_J90_CPU_module.jpg/440px-Cray_J90_CPU_module.jpg)
Последовали и другие примеры. Компания Control Data Corporation попыталась снова выйти на рынок высокопроизводительных компьютеров со своей машиной ETA-10 , но она плохо продавалась, и они воспользовались этим как возможностью полностью покинуть сферу суперкомпьютеров. В начале и середине 1980-х японские компании ( Fujitsu , Hitachi и Nippon Electric Corporation (NEC) представили векторные машины на основе регистров, аналогичные Cray-1, обычно немного быстрее и намного меньше по размеру. Системы с плавающей запятой на основе Орегона (FPS) построили дополнительные массивы процессоров для миникомпьютеров , а позже построили свои собственные мини-суперкомпьютеры .
На протяжении всего времени Cray продолжал оставаться лидером в производительности, постоянно побеждая конкурентов с серией машин, которые привели к Cray-2 , Cray X-MP и Cray Y-MP . С тех пор рынок суперкомпьютеров больше сосредоточился на массовой параллельной обработке, чем на улучшении реализации векторных процессоров. Однако, осознавая преимущества векторной обработки, IBM разработала виртуальную векторную архитектуру для использования в суперкомпьютерах, объединив несколько скалярных процессоров в качестве векторного процессора.
Хотя векторные суперкомпьютеры, похожие на Cray-1, в наши дни менее популярны, NEC продолжает выпускать компьютеры этого типа и по сей день, выпуская компьютеры серии SX . Совсем недавно SX-Aurora TSUBASA размещает процессор и 24 или 48 гигабайт памяти в модуле HBM 2 внутри карты, которая физически напоминает графический сопроцессор, но вместо того, чтобы служить сопроцессором, это главный компьютер с ПК-совместимый компьютер, к которому он подключен, обслуживающий вспомогательные функции.
Одним из крайних и редких примеров процессора массивов был ASP Aspex Microelectronics [2] , который относился к категории «Massive Wide SIMD», но имел ALU на уровне битов и предсказание на уровне битов, и поэтому окончательно мог считаться массивом (вектором). Процессор. [3] [4] Linedancer, выпущенный в 2010 году, содержал 4096 2-битных предустановленных SIMD ALU, каждый со своей собственной адресуемой памятью , и мог выполнять 800 миллиардов инструкций в секунду. [5]
GPU
Современные графические процессоры ( ГП ) включают в себя массив конвейеров шейдеров, которые могут управляться вычислительными ядрами , и могут рассматриваться как векторные процессоры (с использованием аналогичной стратегии для сокрытия задержек памяти). Ключевым отличительным фактором графических процессоров на основе SIMT является то, что у них есть один декодер-широковещатель инструкций, но ядра, принимающие и выполняющие ту же самую инструкцию, в остальном разумно нормальны: их собственные ALU, их собственные файлы регистров, их собственные блоки загрузки / хранения и собственные независимые кеши данных L1. Таким образом, хотя все ядра одновременно выполняют одну и ту же инструкцию синхронно друг с другом, они делают это с совершенно разными данными из совершенно разных ячеек памяти. Это значительно сложнее и сложнее, чем SIMD, который строго ограничен только выполнением параллельных конвейерных арифметических операций. Хотя точные внутренние детали сегодняшних коммерческих графических процессоров являются частной тайной, команда MIAOW [6] смогла собрать воедино анекдотическую информацию, достаточную для реализации подмножества архитектуры AMDGPU. [7]
Сравнение с современной архитектурой
По состоянию на 2016 год[Обновить]большинство стандартных процессоров реализуют архитектуры, которые содержат инструкции SIMD фиксированной длины . При первом осмотре их можно рассматривать как форму векторной обработки, поскольку они работают с множественными наборами данных (векторизованная, явная длина) и заимствуют функции из векторных процессоров. Однако по определению добавление SIMD не может само по себе квалифицировать процессор как фактический векторный процессор, потому что SIMD имеет фиксированную длину, а векторы - переменные. Разница проиллюстрирована ниже с примерами, показывающими и сравнивающими три категории: Pure SIMD, Predicated SIMD и Pure Vector Processing. [ необходима цитата ]
- Чистые (фиксированные) SIMD - Общие примеры использования SIMD с функциями , вдохновленных на векторные процессоры включают Intel x86 в MMX , SSE и AVX инструкции, AMD , 3DNow! расширения, ARM NEON , Sparc в VIS расширение, PowerPC 's AltiVec и MIPS' MSA . В 2000 году IBM , Toshiba и Sony совместно создали процессор Cell , который также называется SIMD .
- Предиктированный SIMD - два примечательных примера с предиктированием на основе каждого элемента (на основе полосы) - это ARM SVE2 и AVX-512.
- Чистые векторы - к ним относятся оригинальные Cray-1 , RISC-V RVV и SX-Aurora TSUBASA . Несмотря на то, что STAR-100 был основан на памяти, он также был векторным процессором.
Другие конструкции процессора включают в себя некоторые нескольких инструкций для векторной обработки на нескольких (vectorised) наборов данных, как правило , известных как MIMD ( М есколько I nstruction, М есколько Д ата) и реализованных с VLIW ( V ERy L Ong Я nstruction Вт ORD). В векторном / VLIW- процессоре Fujitsu FR-V сочетаются обе технологии.
Определение векторной обработки.
Векторные процессоры, по определению и конструкции, всегда были переменной длины с момента их появления.
Там, где чистый (фиксированная ширина, без предсказания) SIMD обычно ошибочно объявляется «векторами», путем тщательного анализа и сравнения исторических и современных ISA обнаруживается, что фактические векторные процессоры можно различить по одной или обоим из двух ключевых характеристик: [ необходима цитата ]
- способ установить
setvl
длину вектора (например, инструкцию в RISCV RVV [8] ) или предоставить функциюREP
(повторение инструкций) в той или иной форме, без ограничения повторов до степени двойки. - исчерпывающие индивидуальные маски предикатов на уровне элементов для каждой векторной инструкции, которые теперь доступны в ARM SVE2. [9] и AVX-512
Разница между чистой (фиксированной длины) SIMD и чистой (переменной длины) векторной обработкой проиллюстрирована ниже в примерах: Предиктированная SIMD, которая использует SIMD ALU фиксированной ширины, но допускает переменную (предсказуемую) активацию единиц для обеспечения видимости переменной длина, находится где-то посередине.
Описание
В общем, ЦП могут управлять одним или двумя частями данных за раз. Например, в большинстве процессоров есть инструкция, которая, по сути, гласит: «добавить A к B и поместить результат в C». Данные для A, B и C могут быть - по крайней мере теоретически - закодированы непосредственно в инструкции. Однако при эффективной реализации редко бывает так просто. Данные редко отправляются в необработанном виде, а вместо этого «указываются» путем передачи адреса в ячейку памяти, в которой хранятся данные. Декодирование этого адреса и извлечение данных из памяти занимает некоторое время, в течение которого ЦП обычно простаивает, ожидая появления запрошенных данных. По мере увеличения скорости ЦП эта задержка памяти исторически становилась большим препятствием для производительности; см. Стена памяти .
Чтобы сократить время, затрачиваемое на эти шаги, большинство современных процессоров используют метод, известный как конвейерная обработка инструкций, при котором инструкции проходят через несколько подблоков по очереди. Первый субблок считывает адрес и декодирует его, следующий «извлекает» значения по этим адресам, а следующий выполняет вычисления самостоятельно. При конвейерной обработке "хитрость" состоит в том, чтобы начать декодирование следующей инструкции еще до того, как первая выйдет из ЦП, как на конвейере , так что декодер адреса постоянно используется. Для выполнения любой конкретной инструкции требуется такое же количество времени, время, известное как задержка , но ЦП может обрабатывать весь пакет операций с перекрытием, намного быстрее и эффективнее, чем если бы он делал это по одной за раз.
Векторные процессоры развивают эту концепцию еще на один шаг. Вместо конвейерной конвейерной обработки только инструкций, они также конвейерно обрабатывают сами данные. Процессор получает инструкции, которые говорят не только о том, чтобы добавить A к B, но и о том, чтобы добавить все числа «отсюда сюда» ко всем числам «оттуда туда». Вместо того , чтобы постоянно имея инструкции декодирования , а затем получать данные , необходимые для их выполнения, процессор считывает одну команду из памяти, и она просто подразумевается в определении инструкции сама , что команда будет работать снова на другой элемент данных, по адресу, на единицу превышающему предыдущий. Это позволяет значительно сэкономить время декодирования.
Чтобы проиллюстрировать, насколько это может отличаться, рассмотрим простую задачу сложения двух групп по 10 чисел. На обычном языке программирования можно было бы написать «цикл», который по очереди выбирал бы каждую из пар чисел, а затем складывал их. Для процессора это выглядело бы примерно так:
; Гипотетическая RISC-машина ; сложить 10 чисел в a к 10 числам в b, сохраняя результаты в c ; предположим, что a, b и c являются ячейками памяти в соответствующих регистрах move $ 10 , count ; count: = 10 loop: load r1 , a load r2 , b add r3 , r1 , r2 ; r3: = r1 + r2 сохранить r3 , c добавить a , a , $ 4 ; перейти к добавлению b , b , $ 4 добавить c , c , 4 $ dec count ; декремент jnez count , loop ; вернуться назад, если счетчик еще не 0 ret
Но для векторного процессора эта задача выглядит значительно иначе:
; предположим, что у нас есть векторные регистры v1-v3 ; при размере, равном или превышающем 10, переместите 10 долларов , считайте ; count = 10 vload v1 , a , count vload v2 , b , count vadd v3 , v1 , v2 vstore v3 , c , count ret
Обратите внимание на полное отсутствие циклов в инструкциях, потому что именно оборудование выполнило 10 последовательных операций: фактически счетчик циклов явно рассчитывается для каждой инструкции .
Векторные ISA в стиле Cray идут дальше и предоставляют глобальный регистр "счетчика", называемый длиной вектора (VL):
; снова предположим, что у нас есть векторные регистры v1-v3 ; с размером больше или равным 10 setvli $ 10 # Установить длину вектора VL = 10 vload v1 , a # 10 загружает из vload v2 , b # 10 загружает из b vadd v3 , v1 , v2 # 10 добавляет vstore v3 , c # 10 магазины в c ret
Такой подход дает несколько преимуществ.
- требуется только три перевода адресов. В зависимости от архитектуры это само по себе может дать значительную экономию.
- Еще одна экономия - выборка и декодирование самой инструкции, которая должна выполняться только один раз вместо десяти.
- Сам код также меньше, что может привести к более эффективному использованию памяти, уменьшению размера кэша инструкций L1, снижению энергопотребления.
- Поскольку длина (эквивалентная ширине SIMD) не жестко закодирована в инструкции, кодировка не только более компактна, но и «ориентирована на будущее» и позволяет даже в конструкциях встроенных процессоров рассматривать использование векторов исключительно для получения всех других преимуществ. , а не стремиться к высокой производительности.
Кроме того, в более современных ISA для векторных процессоров введены функции «Fail on First» или «Fault First» (см. Ниже), что дает еще больше преимуществ.
Но более того, высокопроизводительный векторный процессор может иметь несколько функциональных блоков, добавляющих эти числа параллельно. Проверка зависимостей между этими числами не требуется, поскольку векторная инструкция определяет несколько независимых операций. Это упрощает требуемую логику управления и может дополнительно повысить производительность, избегая остановок. Таким образом, математические операции в целом выполняются намного быстрее, ограничивающим фактором является время, необходимое для извлечения данных из памяти.
Не все проблемы можно решить с помощью такого рода решений. Включение этих типов инструкций обязательно усложняет основной ЦП. Эта сложность обычно заставляет другие инструкции выполняться медленнее, т. Е. Всякий раз, когда они не суммируют много чисел подряд. Более сложные инструкции также усложняют декодеры, что может замедлить декодирование более общих инструкций, таких как обычное сложение. ( Это можно несколько смягчить, сохранив все принципы ISA в соответствии с принципами RISC : RVV добавляет только около 190 векторных инструкций даже с расширенными функциями. [10] )
Векторные процессоры традиционно разрабатывались так, чтобы лучше всего работать только тогда, когда нужно обрабатывать большие объемы данных. По этой причине такие типы процессоров использовались в основном в суперкомпьютерах , поскольку сами суперкомпьютеры , как правило, находились в таких местах, как центры прогнозирования погоды и физические лаборатории, где «обрабатываются» огромные объемы данных. Однако, как показано выше и продемонстрировано RISC-V RVV, эффективность Vector ISA дает другие преимущества, которые очевидны даже для встраиваемых сценариев использования.
Векторные инструкции
Приведенный выше пример векторного псевдокода исходит из большого предположения, что векторный компьютер может обрабатывать более десяти чисел за один пакет. При большем количестве чисел в векторном регистре для компьютера становится невозможным иметь регистр такого размера. В результате векторный процессор либо получает возможность выполнять циклы сам, либо предоставляет программисту какой-то регистр векторного управления (состояния), обычно известный как длина вектора.
Самовоспроизводящиеся инструкции можно найти в ранних векторных компьютерах, таких как STAR-100, где вышеупомянутое действие было бы описано в одной инструкции (что-то вроде vadd c, a, b, $10
). Они также встречаются в архитектуре x86 в качестве REP
префикса. Однако таким образом аппаратно можно эффективно выполнять только очень простые вычисления без очень большого увеличения стоимости. Поскольку все операнды должны находиться в памяти для архитектуры STAR-100, задержка, вызванная доступом, также становится огромной.
Интересно, что Broadcom включил пробел во все векторные операции Videocore IV ISA для REP
поля, но в отличие от STAR-100, который использует память для своих повторов, Videocore IV повторяет все операции, включая арифметические векторные операции. Длина повтора может быть в небольшом диапазоне степени двойки или определяться одним из скалярных регистров. [11]
Cray-1 представил идею использования регистров процессора для удержания векторных данных в пакетном режиме. Длины пакетов (длина вектора, VL) могут быть динамически установлены с помощью специальной инструкции, значимость по сравнению с Videocore IV (и, что особенно важно, как будет показано ниже, также с SIMD) в том, что длина повтора не обязательно должна быть частью кодировка инструкции. Таким образом, в каждом пакете можно проделать гораздо больше работы, а кодирование инструкций станет более элегантным и компактным, единственный недостаток состоит в том, что для того, чтобы в полной мере использовать эту дополнительную производительность пакетной обработки, соответственно были загружены память и скорость хранения также увеличиваться. Иногда это называют недостатком векторных процессоров в стиле Cray: на самом деле это просто соответствует территории достижения высокой пропускной способности, как это видно на графических процессорах , которые сталкиваются с точно такой же проблемой. Говоря простым языком: вы хотите вычислять числа, вам нужна пропускная способность.
Современные SIMD- компьютеры утверждают, что улучшили ранний Cray за счет прямого использования нескольких ALU для более высокой степени параллелизма по сравнению с использованием только обычного скалярного конвейера. Современные векторные процессоры (такие как SX-Aurora TSUBASA ) объединяют и то, и другое, передавая несколько данных нескольким внутренним конвейерным SIMD ALU, причем выданный номер динамически выбирается векторной программой во время выполнения. Маски можно использовать для выборочной загрузки и хранения данных в ячейках памяти, а также использовать те же маски для выборочного отключения элемента обработки SIMD ALU. Некоторые чистые процессоры SIMD ( AVX-512 , ARM SVE2 ) способны к такого рода выборочной, покойной ( «предикативной» ) обработке, и именно они в некоторой степени заслуживают наименования «векторный процессор» или, по крайней мере, заслуживают того, чтобы претендовать на звание «векторный процессор». возможность "векторной обработки". Процессоры SIMD без предиката для каждого элемента ( MMX , SSE , AltiVec ) категорически этого не делают.
Современные графические процессоры, которые имеют множество небольших вычислительных блоков, каждый из которых имеет свои собственные независимые SIMD ALU, используют нечто, называемое Single Instruction Multiple Threads (SIMT). Блоки SIMT запускаются из единого совместно используемого блока инструкций, синхронизированного по широковещательной передаче. «Векторные регистры» очень широки, а конвейеры имеют тенденцию быть длинными. «Потоковая» часть SIMT включает способ обработки данных независимо на каждом из вычислительных блоков.
Кроме того, графические процессоры, такие как Broadcom Videocore IV, и другие внешние векторные процессоры, такие как NEC SX-Aurora TSUBASA, могут использовать меньшее количество векторных единиц, чем предполагает ширина: вместо 64 единиц для 64-числового регистра может использоваться аппаратное обеспечение. сделать конвейерный цикл более 16 единиц для гибридного подхода. Broadcom Videocore IV также может использовать этот гибридный подход: номинально заявляя, что его SIMD QPU Engine поддерживает в своих инструкциях 16-длинных операций массива FP, он фактически выполняет их 4 за раз, как форму «потоков». [12]
Пример векторной инструкции
В этом примере мы начинаем с алгоритма («IAXPY»), сначала показываем его в скалярных инструкциях, затем в SIMD, затем в предиктированном SIMD и, наконец, в векторных инструкциях. Это помогает проиллюстрировать разницу между традиционным векторным процессором и современным SIMD-процессором. Начнем с 32-битного целочисленного варианта функции DAXPY в c :
void iaxpy ( size_t n , int a , const int x [], int y []) { for ( size_t i = 0 ; i < n ; i ++ ) y [ i ] = a * x [ i ] + y [ i ]; }
Скалярный ассемблер
Наша скалярная версия этого загружает по одному из x и y, обрабатывает одно вычисление, сохраняет один результат и выполняет цикл:
цикл: load32 r1 , x ; загрузить одну 32- битную загрузку данных 32 r2 , y mul32 r1 , a , r1 ; r1: = r1 * a add32 r3 , r1 , r2 ; r3: = r1 + r2 store32 r3 , y addl x , x , $ 4 ; x: = x + 4 addl y , y , $ 4 subl n , n , $ 1 ; n: = n - 1 jgz n , петля ; вернуться назад, если n> 0 out: ret
Код, подобный STAR, остается кратким, но поскольку векторизация STAR-100 была по замыслу основана на доступе к памяти, нам теперь требуется дополнительный слот памяти для обработки информации. Также требуется двукратная задержка из-за дополнительных требований доступа к памяти.
; Предположим, что tmp заранее выделен vmul tmp , a , x , n ; tmp [i] = a * x [i] vadd y , y , tmp , n ; y [i] = y [i] + tmp [i] ret
Чистый (без предиката) SIMD
Современный SIMD-аппарат может выполнять большую часть операций партиями. Код во многом похож на скалярную версию. Мы предполагаем, что и x, и y здесь правильно выровнены и что n кратно 4, так как в противном случае потребуется некоторый установочный код для вычисления маски или для запуска скалярной версии. Мы также предполагаем, для простоты, что инструкции SIMD имеют возможность автоматически повторять скалярные операнды, как это может делать ARM NEON. [13] Если это не так, необходимо использовать "splat" (широковещательную рассылку), чтобы скопировать скалярный аргумент через регистр SIMD:
splatx4 v4 , a ; v4 = а, а, а, а
Затраченное время будет в основном таким же, как и для векторной реализации, c = a + b
описанной выше.
vloop: load32x4 v1 , x load32x4 v2 , y mul32x4 v1 , a , v1 ; v1: = v1 * a add32x4 v3 , v1 , v2 ; v3: = v1 + v2 store32x4 v3 , y addl x , x , $ 16 ; x: = x + 16 addl y , y , $ 16 subl n , n , $ 4 ; n: = n - 4 jgz n , vloop ; вернуться, если n> 0 out: ret
Обратите внимание, что указатели x и y увеличиваются на 16, потому что это длина (в байтах) четырех 32-битных целых чисел. Было принято решение, что алгоритм будет работать только с 4-мя SIMD, поэтому константа жестко запрограммирована в программе.
К сожалению, для SIMD ключ кроется в предположении выше, «что n кратно 4», а также в «согласованном доступе», что, очевидно, является ограниченным вариантом использования для специалистов.
Реально, для циклов общего назначения, таких как переносимые библиотеки, где n не может быть ограничено таким образом, накладные расходы на настройку и очистку для SIMD, чтобы справиться с не кратными ширине SIMD, могут намного превышать количество инструкций внутри сама петля. Предполагая, что в наихудшем случае оборудование не может выполнять несогласованные обращения к памяти SIMD, реальный алгоритм сначала должен иметь подготовительную секцию, которая работает с начальными невыровненными данными, вплоть до первой точки, в которой операции, выровненные с памятью SIMD, могут взять верх. SIMD шириной восемь требует повторения алгоритма внутреннего цикла сначала с элементами SIMD шириной четыре, затем SIMD шириной две, затем одним (скалярным), с тестом и переходом между каждым из них, чтобы покрыть первый и последний оставшиеся SIMD. элементы (0 <= n <= 7).
Это более чем втрое увеличивает размер кода, а в крайних случаях приводит к увеличению количества инструкций на порядок ! Это может быть легко продемонстрировано путем компиляции iaxpy примера AVX512, используя параметры "-O3 -march=knl"
для GCC .
Со временем, по мере того, как ISA развивается, чтобы постоянно увеличивать производительность, это приводит к тому, что ISA Architects добавляют SIMD ширины 2, затем SIMD 4 ширины, затем 8 ширины и выше. Таким образом, мы начинаем понимать, почему AVX-512 существует в x86.
Без предсказания, чем шире ширина SIMD, тем хуже становятся проблемы, что приводит к массовому распространению опкодов. Vector ISA требует только одного набора операций, обеспечивая покрытие данных переменной длины независимо от внутреннего оборудования. [14]
С другой стороны, векторные процессоры предназначены для выполнения вычислений переменной длины для произвольного числа n и, следовательно, требуют очень небольшой настройки и никакой очистки. Даже по сравнению с теми SIMD ISA, у которых есть маски (но без setvl
инструкций), векторные процессоры создают гораздо более компактный код, потому что им не нужно выполнять явное вычисление маски для покрытия последних нескольких элементов (показано ниже).
Предоставленный SIMD
Предполагая гипотетический предиктированный (поддерживающий маску) SIMD ISA, цикл инструкций будет выглядеть следующим образом:
vloop: # подготовить маску. немного ISA имеют min, хотя min t0 , n , 4 доллара США ; t0 = min (n, 4) сдвиг m , $ 1 , t0 ; m = 1 << t0 sub m , m , $ 1 ; m = (1 << t0) -1 # теперь выполняем операцию, маскируемую m битами load32x4 v1 , x , m load32x4 v2 , y , m mul32x4 v1 , a , v1 , m ; v1: = v1 * a add32x4 v3 , v1 , v2 , m ; v3: = v1 + v2 store32x4 v3 , y , m # обновить x, y и n для следующего цикла addl x , t0 * 4 ; x: = x + t0 * 4 addl y , t0 * 4 subl n , n , t0 ; n: = n - t0 # цикл? jgz n , vloop ; вернуться, если n> 0 out: ret
Здесь мы видим, что код намного чище, но немного сложнее: по крайней мере, однако здесь нет настройки или очистки: на последней итерации цикла маска предиката будет установлена на 0b0000, 0b0001, 0b0011, 0b0111 или 0b1111 , в результате чего выполняется от 0 до 4 операций с элементами SIMD соответственно. Еще одна потенциальная сложность: некоторые ISA RISC не имеют инструкции «min», и вместо этого требуется использовать ветвление или скалярное сравнение с предикатом.
Понятно, насколько предикативная SIMD по крайней мере заслуживает термина «способный к вектору», потому что она может справиться с векторами переменной длины с помощью предикатных масок. Последний шаг в развитии «истинного» Vector ISA, однако, состоит в том, чтобы не иметь никаких свидетельств в ISA вообще о ширине SIMD, оставляя это полностью на усмотрение оборудования.
Чистый (истинный) вектор ISA
Для векторных ISA в стиле Cray, таких как RVV, используется инструкция "setvl" (установка длины вектора). Аппаратное обеспечение сначала определяет, сколько значений данных оно может обработать в одном «векторе»: это могут быть либо фактические регистры, либо внутренний цикл (гибридный подход, упомянутый выше). Это максимальное количество (количество аппаратных «дорожек») называется «MVL» (максимальная длина вектора). Обратите внимание, что, как мы видели в SX-Aurora и Videocore IV, MVL может быть фактическим количеством аппаратных дорожек или виртуальным . (Примечание: как упоминалось в руководстве по ARM SVE2, программисты не должны совершать ошибку, предполагая фиксированную ширину вектора: следовательно, MVL не является величиной, которую программист должен знать. Это может немного сбить с толку после многих лет мышления SIMD).
При вызове setvl с количеством необработанных элементов данных, которые должны быть обработаны, «setvl» разрешено (больше похоже, необходимо) ограничить это значение максимальной длиной вектора (MVL) и, таким образом, возвращает фактическое число, которое может быть обработано оборудованием в последующих векторных инструкций и устанавливает во внутреннем специальном регистре «VL» то же самое количество. ARM в своих руководствах по SVE2 называет эту технику программированием, не зависящим от длины вектора. [15]
Ниже представлен векторный ассемблер в стиле Cray для того же цикла в стиле SIMD, описанный выше. Посмотрите внимательно, как t0 (который может варьироваться) используется вместо жестко запрограммированных констант:
vloop: setvl t0 , n # VL = t0 = min (MVL, n) vld32 v0 , x # вектор нагрузки x vld32 v1 , y # вектор нагрузки y vmadd32 v1 , v0 , a # v1 + = v0 * a vst32 v1 , y # сохранить Y add y , t0 * 4 # продвинуть y на VL * 4 add x , t0 * 4 # продвинуть x на VL * 4 sub n , t0 # n - = VL (t0) bnez n , vloop # повторить, если n! = 0
На самом деле это не сильно отличается от версии SIMD (обрабатывает 4 элемента данных за цикл) или от начальной скалярной версии (обрабатывает только один). Мы можем видеть , что п еще содержит число элементов данных , оставшихся подлежащую обработке, но что t0 содержит копию VL - номер , который Собирается будет обрабатываться в каждой итерации. t0 вычитается из n после каждой итерации, и если n равно нулю, то все элементы были обработаны.
При сравнении с вариантом сборки Predicated SIMD следует отметить ряд интересных моментов:
setvl
инструкция имеет встроенный в негоmin
инструкции- Если вариант SIMD жестко закодировал как ширину (4), если маска, так и ширину SIMD (load32x4 и т. Д.), Эквиваленты Vector ISA не имеют такого ограничения. Это делает программы Vector одновременно портативными, независимыми от поставщиков и ориентированными на будущее.
- установка VL эффективно создает скрытую маску предиката, которая автоматически применяется к векторам
- Там, где с Predicated SIMD длина битов маски ограничена значением, которое может храниться в скалярном (или специальном) регистре, регистры маски Vector ISA не имеют такого ограничения. В векторах Cray-I могло быть чуть более 1000 элементов (в 1977 году).
Таким образом, мы можем очень ясно увидеть, как Vector ISA сокращает количество инструкций.
Также обратите внимание, что, как и в варианте Predicated SIMD, указатели на x и y увеличиваются в t0 раз в четыре раза, потому что оба они указывают на 32-битные данные, но это n уменьшается на прямое t0. По сравнению с ассемблером SIMD фиксированного размера разница очень небольшая: x и y увеличиваются на жестко запрограммированную константу 16, n уменьшается на жестко запрограммированную 4, поэтому поначалу трудно оценить важность. Разница заключается в осознании того, что аппаратное обеспечение Vector может выполнять 4 одновременных операции, или 64, или 10 000, это будет один и тот же Vector Assembler для всех из них, и все равно не будет кода очистки SIMD . Даже по сравнению с SIMD с поддержкой Predicate, он по-прежнему более компактен, понятнее, элегантнее и потребляет меньше ресурсов.
У нас есть не только гораздо более компактная программа (экономия на размере кэша L1), но, как уже упоминалось ранее, версия Vector может выполнять гораздо больше обработки данных для ALU, опять же, экономя энергию, потому что Instruction Decode и Issue могут бездействовать.
Еще один интересный аспект: количество элементов, входящих в функцию, может начинаться с нуля . Это устанавливает длину вектора равной нулю, что эффективно отключает все инструкции вектора, превращая их в запретные операции во время выполнения. Таким образом, в отличие от непредсказуемого SIMD, даже если нет элементов для обработки, все равно не будет потраченного впустую кода очистки.
Возможности векторного процессора
Типичные особенности хорошего векторного процессора: [16] [17] [18]
- Загрузка и хранение векторных данных - они по своей сути экономят на поиске в виртуальной памяти и предназначены для помещения данных в регистры с минимальными усилиями. Расширенные усовершенствования векторной загрузки / сохранения включают поддержку упаковки структуры , Fail-First, Gather-scatter , Indexed, Unit и Element.
- Маскированные операции - как теперь обычно используются в графических процессорах , маски предикатов позволяют выполнять параллельные конструкции if / then / else без ветвей (которые по своей природе скалярны)
- Сжатие и расширение - обычно с использованием битовой маски данные линейно сжимаются или расширяются (перераспределяются) в зависимости от того, установлены ли биты в маске или очищены, при этом всегда сохраняется последовательный порядок и никогда не дублируются значения (в отличие от Gather-Scatter aka permute) . Эти инструкции доступны в AVX-512
- Register Gather, Scatter (aka permute) [19] - менее ограничительный, более общий вариант темы Compress / Expand, который вместо этого использует один вектор для определения индексов, которые будут использоваться для «переупорядочивания» другого вектора. Gather / Scatter реализовать сложнее, чем Compress / Expand, и, будучи по своей сути непоследовательным, может мешать объединению векторов . Не путать с режимами загрузки / сохранения в память Gather-scatter, операции Gather / Scatter Vector действуют в векторных регистрах и вместо этого часто называются инструкциями перестановки .
- Splat и Extract - полезны для взаимодействия между Scalar и Vector, они передают одно значение по вектору или извлекают один элемент из вектора, соответственно.
- Йота - очень простая и стратегически полезная инструкция, которая сразу же переходит в последовательные элементы. Обычно начинается с нуля.
- Редукция и итерация - операции, выполняющие mapreduce для вектора (например, найти одно максимальное значение всего вектора или суммировать все элементы). Итерация имеет вид,
x[i] = y[i] + x[i-1]
где редукция имеет видx = y[0] + y[1]… + y[n-1]
- Поддержка умножения матриц - либо путем алгоритмической загрузки данных из памяти, либо путем переупорядочивания (переназначения) обычного линейного доступа к элементам вектора, либо путем предоставления «аккумуляторов» матрицы произвольного размера могут быть эффективно обработаны. IBM POWER10 предоставляет инструкции MMA [20], хотя для произвольной ширины матрицы, которая не соответствует точному размеру SIMD, необходимы методы повторения данных, что приводит к расточительному использованию ресурсов регистрового файла. [21] Aspex ASP Linedancer имел механизм DMA с переупорядочиванием памяти 2D / 3D, который требовал значительных усилий для оптимального использования. [22] [23] . NVidia предоставляет высокоуровневый Matrix CUDA API, хотя внутренние детали недоступны. [24] Наиболее ресурсоэффективным методом является изменение порядка доступа к линейным векторным данным на месте.
- Расширенные математические форматы - часто включают арифметику поля Галуа , но могут включать десятичную дробь с двоичным кодом или десятичную фиксированную точку, а также поддержку гораздо более крупных (произвольной точности) арифметических операций за счет поддержки параллельного переноса и переноса.
- Битовые манипуляции - включая векторизованные версии операций перестановки на уровне битов, вставку и извлечение битовых полей, операции центрифугирования, подсчет населения и многие другие .
Возможности векторной обработки на GPU
Поскольку многие приложения 3D- шейдеров нуждаются в тригонометрических операциях, а также в коротких векторах для общих операций (RGB, ARGB, XYZ, XYZW), в современных графических процессорах, помимо тех, что есть в векторных процессорах, обычно присутствует поддержка следующего:
- Субвекторы - элементы обычно могут содержать два, три или четыре субэлемента (vec2, vec3, vec4), где любой заданный бит маски предиката применяется ко всему вектору vec2 / 3/4, а не к элементам в субвекторе . Субвекторы также представлены в RISC-V RVV (называемом «LMUL»). [25] . Подвекторы являются важной составной частью спецификации Vulkan SPIR-V .
- Sub-vector Swizzle - он же « перетасовка дорожек », который позволяет выполнять вычисления между субвекторами между элементами без необходимости в дополнительных (дорогостоящих, расточительных) инструкциях для перемещения субэлементов в правильные «дорожки» SIMD. Также сохраняет биты маски предиката. По сути, это мини-перестановка субвектора в полете , в значительной степени функциональная в двоичных файлах 3D-шейдеров, и достаточно важна, чтобы быть частью спецификации Vulkan SPIR-V . Broadcom Videocore IV использует терминологию «Lane Rotate » [26], тогда как остальная часть индустрии использует термин «swizzle» . [27]
- Трансцендентальные числа - тригонометрические операции, такие как синус , косинус и логарифм, очевидно, в большей степени используются в 3D, чем во многих ресурсоемких рабочих нагрузках высокопроизводительных вычислений . Однако интересно то, что скорость намного важнее точности в 3D для графических процессоров, где вычисление координат пикселей просто не требует высокой точности. Спецификация Vulkan учитывает это и устанавливает удивительно низкие требования к точности, так что аппаратное обеспечение графического процессора может снизить потребление энергии. Концепция снижения точности там, где она просто не нужна, исследуется в расширении MIPS-3D . Также обычно присутствует векторная нормализация, а также скалярное произведение .
Дополнительную информацию и подсказки по функциям GPU Vector ISA можно найти, изучив спецификацию SPIR-V , [28] спецификацию Vulkan [29] и спецификацию OpenCL . [30] Эти API-интерфейсы были созданы Khronos Group такими членами, как Intel, Google, AMD и NVIDIA, и, таким образом, дают представление о функциях, предоставляемых самыми быстрыми графическими процессорами в мире. Также может помочь переработанный набор инструкций графического процессора MALI Midgard. [31]
Сначала неисправность (или отказ)
В ARM SVE2 и RISC-V RVV введена концепция спекулятивных последовательных векторных нагрузок. ARM SVE2 имеет специальный регистр «Регистр первого сбоя» [32], где RVV изменяет (обрезает) длину вектора (VL). [33]
Базовый принцип ffirst - попытаться выполнить большую последовательную векторную загрузку, но позволить оборудованию произвольно усечь фактический загруженный объем либо до суммы, которая будет успешной без возникновения ошибки памяти, либо просто до суммы (больше нуля), которая равна Самый удобный. Важным фактором является то, что последующие инструкции уведомляются или могут точно определять, сколько загрузок фактически выполнено, используя это количество только для выполнения работы с данными, которые были фактически загружены.
Сравните эту ситуацию с SIMD, который представляет собой фиксированную (негибкую) ширину загрузки и фиксированную ширину обработки данных, неспособную справиться с нагрузками, пересекающими границы страницы, и даже если бы они были, они неспособны адаптироваться к тому, что на самом деле удалось, но, как это ни парадоксально, если программа SIMD даже попытается заранее выяснить (в каждом внутреннем цикле, каждый раз), что может быть оптимально успешным, эти инструкции будут только снижать производительность, потому что они по необходимости будут частью критического внутреннего цикла.
Это начинает намекать на причину, по которой ffirst является таким инновационным, и лучше всего иллюстрируется memcpy или strcpy, когда они реализованы со стандартным 128-битным не-предикатным non-ffirst SIMD. Для IBM POWER9 количество оптимизированных вручную инструкций для реализации strncpy превышает 240 [34] . Напротив, та же самая процедура strncpy в оптимизированном вручную ассемблере RVV состоит всего из 22 инструкций. [35]
Вышеупомянутый пример SIMD потенциально может дать сбой и сбой в конце памяти из-за попыток чтения слишком большого количества значений: он также может вызвать значительное количество ошибок страницы или смещения из-за аналогичного пересечения границ. Напротив, предоставляя векторной архитектуре свободу решать, сколько элементов загружать, первая часть strncpy, если она начинается изначально на неоптимальной границе памяти, может возвращать достаточно нагрузок, так что при последующих итерациях цикла пакеты чтения векторизованной памяти оптимально согласованы с базовыми кэшами и механизмами виртуальной памяти. Кроме того, оборудование может решить использовать возможность завершения любой данной итерации цикла чтения памяти точно на границе страницы (избегая дорогостоящего второго поиска TLB), при спекулятивном выполнении, подготавливающем следующую страницу виртуальной памяти, в то время как данные все еще обрабатываются в текущем петля. Все это определяется оборудованием , а не самой программой. [36]
Производительность и ускорение
Пусть r - коэффициент векторной скорости, а f - коэффициент векторизации. Если время, затрачиваемое векторным блоком на добавление массива из 64 чисел, в 10 раз быстрее, чем у его эквивалентного скалярного аналога, r = 10. Кроме того, если общее количество операций в программе равно 100, из которых только 10 являются скалярными. (после векторизации), то f = 0,9, т.е. 90% работы выполняет векторный блок. Это следует за достижимым ускорением:
Таким образом, даже если производительность векторного блока очень высока () мы получаем ускорение меньше чем , что предполагает, что отношение f имеет решающее значение для производительности. Это соотношение зависит от эффективности компиляции, например, от смежности элементов в памяти.
Программирование гетерогенных вычислительных архитектур
Были разработаны различные машины, включающие как традиционные процессоры, так и векторные процессоры, такие как Fujitsu AP1000 и AP3000. Программирование таких разнородных машин может быть трудным, поскольку разработка программ, наилучшим образом использующих характеристики различных процессоров, увеличивает нагрузку на программиста. Это увеличивает сложность кода и снижает переносимость кода, требуя, чтобы код, специфичный для оборудования, чередовался по всему коду приложения. [37] Балансировка нагрузки приложения между процессорами может быть проблематичной, особенно с учетом того, что они обычно имеют разные характеристики производительности. Существуют различные концептуальные модели для решения проблемы, например, с использованием языка координации и строительных блоков программы (программных библиотек или функций более высокого порядка). У каждого блока может быть своя собственная реализация для каждого типа процессора. Пользователи просто программируют, используя эти абстракции, а интеллектуальный компилятор выбирает лучшую реализацию на основе контекста. [38]
Смотрите также
- Архитектура SX
- Таксономия Дункана о конвейерных векторных процессорах
- ГПГПУ
- Вычислить ядро
- Потоковая обработка
- SIMD
- Автоматическая векторизация
- Цепочка (векторная обработка)
- Компьютер для работы с функциями
- RISC-V , открытый стандарт ISA со связанным расширением вектора переменной ширины .
- Бочковой процессор
- Блок тензорной обработки
- История суперкомпьютеров
- Архитектура суперкомпьютера
Рекомендации
- ↑ Малиновский, Б.Н. (1995). История компьютерных технологий в их лицах . Киев: Фирма "КИТ". ISBN 5-7707-6131-8.
- ^ [1]
- ^ [2]
- ^ [3]
- ^ Aspex Linedancer HD
- ^ Вертикальная исследовательская группа MIAOW
- ^ MIAOW GPU
- ^ [4]
- ^ [5]
- ^ [6]
- ^ Руководство программиста Videocore IV
- ^ Videocore IV QPU анализ Джеффа Буша
- ^ [7]
- ^ SIMD считается вредным
- ^ Учебное пособие по ARM SVE2
- ^ Обзор Cray
- ^ RISC-V RVV ISA
- ^ Обзор SX-Arora
- ^ Инструкции по сбору-разбросу регистра RVV
- ^ [8]
- ^ [9]
- ^ [10]
- ^ [11]
- ^ [12]
- ^ LMUL> 1 в RVV
- ^ Заброшенный патент США US20110227920-0096
- ^ Videocore IV QPU
- ^ [13]
- ^ [ https://www.khronos.org/registry/vulkan/ ]
- ^ [14]
- ^ [15]
- ^ Введение в ARM SVE2
- ^ Нагрузки RVV с первым отказом
- ^ ПАТЧ к libc6 для добавления оптимизированного strncpy POWER9
- ^ Пример RVV strncpy
- ^ Статья ARM SVE2 Н. Стивенса
- ^ Кунцман, DM; Кале, LV (2011). «Программирование гетерогенных систем». 2011 Международный симпозиум IEEE по параллельной и распределенной обработке, семинары и Phd Forum . п. 2061. DOI : 10,1109 / IPDPS.2011.377 . ISBN 978-1-61284-425-1.
- ^ Джон Дарлинтон; Мустафа Ганем; Йике Го; Хинг Винг То (1996), "Управляемая организация ресурсов в гетерогенных параллельных вычислениях", Журнал высокопроизводительных вычислений , 4 (1): 13–23, CiteSeerX 10.1.1.37.4309
Внешние ссылки
- История развития параллельных вычислений (с 1955 по 1993 год)
- Векторные вычисления, прошлое, настоящее и будущее, Стив Скотт, Cray Inc.
- Руководство по NEC SX-Aurora ISA
- Ресурсы Broadcom VideoCore IV
- RISC-V Vectors, CS152, весна 2020 г.
- Справочное руководство по аппаратному обеспечению Cray-i, главы 1-3
- Справочное руководство по аппаратному обеспечению Cray-I 1977 г.