В вычислении , A вектор процессор или массив процессора является центральный процессор (ЦП) , который реализует набор команд , где его инструкции предназначены для эффективной и эффективной работы на больших одномерных массивов данных , называемых векторов . Это отличается от скалярных процессоров , инструкции которых работают только с отдельными элементами данных, и от некоторых из тех же скалярных процессоров, имеющих дополнительные арифметические блоки SIMD или SWAR . Векторные процессоры могут значительно повысить производительность при определенных рабочих нагрузках, в частностичисленное моделирование и аналогичные задачи. Методы векторной обработки также работают в аппаратном обеспечении игровой приставки и в графических ускорителях .
Векторные машины появились в начале 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 для каждого элемента данных не является общим для более поздних проектов и часто упоминается в отдельной категории - массово-параллельные вычисления. Примерно в это же время Флинн классифицировал этот тип обработки как раннюю форму SIMT .
Компьютер для операций с функциями был представлен и разработан Карцева в 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 - намного быстрее, чем любая машина того времени.
Последовали и другие примеры. Компания 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], который классифицировал себя как «массивный широкий SIMD», но имел ALU на уровне битов и предсказание на уровне битов, и поэтому окончательно мог считаться массивом (вектором). Процессор. [3] [4] Linedancer, выпущенный в 2010 году, содержал 4096 2-битных предустановленных SIMD ALU, каждый со своей собственной адресуемой памятью , и мог выполнять 800 миллиардов инструкций в секунду. [5] Интересно, что согласно таксономии Флинна ASP был одновременно ассоциативным процессором и процессором массива.
GPU
Современные графические процессоры ( ГП ) включают в себя массив конвейеров шейдеров, которые могут управляться вычислительными ядрами , и могут рассматриваться как векторные процессоры (с использованием аналогичной стратегии для сокрытия задержек памяти). Как показано в статье Флинна 1972 года, ключевым отличительным фактором графических процессоров на основе SIMT является то, что у них есть один декодер-широковещатель инструкций, но ядра, принимающие и выполняющие ту же инструкцию, в остальном вполне нормальны: их собственные ALU, их собственные файлы регистров, их собственные блоки загрузки / хранения и собственные независимые кеши данных L1. Таким образом, хотя все ядра одновременно выполняют одну и ту же инструкцию синхронно друг с другом, они делают это с совершенно разными данными из совершенно разных ячеек памяти. Это значительно сложнее и сложнее, чем "Packed SIMD" , который строго ограничен только выполнением параллельных конвейерных арифметических операций. Хотя точные внутренние детали сегодняшних коммерческих графических процессоров являются частной тайной, команда MIAOW [6] смогла собрать воедино анекдотическую информацию, достаточную для реализации подмножества архитектуры AMDGPU. [7]
Сравнение с современной архитектурой
По состоянию на 2016 год[Обновить]большинство стандартных процессоров реализуют архитектуры, которые содержат инструкции SIMD фиксированной длины . При первом осмотре их можно рассматривать как форму векторной обработки, поскольку они работают с множественными наборами данных (векторизованная, явная длина) и заимствуют функции из векторных процессоров. Однако по определению добавление SIMD не может само по себе квалифицировать процессор как фактический векторный процессор, потому что SIMD имеет фиксированную длину, а векторы - переменные. Разница проиллюстрирована ниже с примерами, показывающими и сравнивающими три категории: Pure SIMD, Predicated SIMD и Pure Vector Processing. [ необходима цитата ]
- Чистый (фиксированный) SIMD - также известный как «упакованный SIMD», [8] SIMD в регистре (SWAR) и конвейерный процессор в Таксономии Флинна. Распространенные примеры использования 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 обычно ошибочно объявляется «векторами» (поскольку SIMD используется для обработки данных, которые являются векторами), посредством тщательного анализа и сравнения исторических и современных ISA фактические векторные процессоры являются обнаружено, что его можно различить по одной или обоим из двух ключевых характеристик: [ необходима цитата ]
- способ установить
setvl
длину вектора (например, инструкцию в RISCV RVV [9] ) или предоставить функциюREP
(повторение инструкций) в той или иной форме, без ограничения повторов до степени двойки. - Итерация и сокращение элементов в векторах. Векторы RISC-V версии 0.10 имеют только сокращение, в то время как Cray-1 и SX-Aurora имеют итерацию, а также сокращение. [10] [11] [12]
Предиктированный SIMD (часть таксономии Флинна ), который представляет собой комплексные маски предикатов на уровне отдельных элементов для каждой векторной инструкции, которые теперь доступны в ARM SVE2. [13] и AVX-512 , почти можно квалифицировать как векторный процессор. Predicated SIMD использует SIMD ALU фиксированной ширины, но позволяет локально управляемую (предикативную) активацию модулей, чтобы обеспечить появление векторов переменной длины. Примеры, приведенные ниже, помогают объяснить эти категориальные различия.
SIMD , поскольку он представляет собой пакетную обработку фиксированной ширины, по своей конструкции не может справиться с итерацией и сокращением. Это дополнительно проиллюстрировано примерами ниже.
Описание
В общем, ЦП могут управлять одним или двумя частями данных за раз. Например, в большинстве процессоров есть инструкция, которая, по сути, гласит: «добавить 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
Такой подход дает несколько преимуществ. [14]
- требуется только три перевода адресов. В зависимости от архитектуры это само по себе может дать значительную экономию.
- Еще одна экономия - выборка и декодирование самой инструкции, которая должна выполняться только один раз вместо десяти.
- Сам код также меньше, что может привести к более эффективному использованию памяти, уменьшению размера кэша инструкций L1, снижению энергопотребления.
- При уменьшении размера программы прогнозирование ветвлений становится более легкой задачей.
- Поскольку длина (эквивалентная ширине SIMD) не жестко закодирована в инструкции, кодировка не только более компактна, но и «ориентирована на будущее» и позволяет даже в конструкциях встроенных процессоров рассматривать использование векторов исключительно для получения всех других преимуществ. , а не стремиться к высокой производительности.
Кроме того, в более современных ISA для векторных процессоров введены функции «Fail on First» или «Fault First» (см. Ниже), что дает еще больше преимуществ.
Но более того, высокопроизводительный векторный процессор может иметь несколько функциональных блоков, добавляющих эти числа параллельно. Проверка зависимостей между этими числами не требуется, поскольку векторная инструкция определяет несколько независимых операций. Это упрощает требуемую логику управления и может дополнительно повысить производительность, избегая остановок. Таким образом, математические операции в целом выполняются намного быстрее, ограничивающим фактором является время, необходимое для извлечения данных из памяти.
Не все проблемы можно решить с помощью такого рода решений. Включение этих типов инструкций обязательно усложняет основной ЦП. Эта сложность обычно заставляет другие инструкции выполняться медленнее, т. Е. Всякий раз, когда они не суммируют много чисел подряд. Более сложные инструкции также усложняют декодеры, что может замедлить декодирование более общих инструкций, таких как обычное сложение. ( Это можно несколько смягчить, сохранив все принципы ISA для RISC : RVV добавляет только около 190 векторных инструкций даже с расширенными функциями. [15] )
Векторные процессоры традиционно разрабатывались так, чтобы лучше всего работать только тогда, когда нужно обрабатывать большие объемы данных. По этой причине такие типы процессоров использовались в основном в суперкомпьютерах , поскольку сами суперкомпьютеры , как правило, находились в таких местах, как центры прогнозирования погоды и физические лаборатории, где «обрабатываются» огромные объемы данных. Однако, как показано выше и продемонстрировано 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 повторяет все операции, включая арифметические векторные операции. Длина повтора может быть в небольшом диапазоне степени двойки или определяться одним из скалярных регистров. [16]
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 за раз, как (еще одна) форма «потоков». [17]
Пример векторной инструкции
В этом примере мы начинаем с алгоритма («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 ]; }
На каждой итерации каждый элемент y имеет элемент x, умноженный на a и добавленный к нему. Программа представлена в скалярной линейной форме для удобства чтения.
Скалярный ассемблер
Наша скалярная версия этого загружает по одному из 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
Современная архитектура Packed SIMD, известная под многими именами (перечисленными в таксономии Флинна ), может выполнять большую часть операций в пакетном режиме. Код во многом похож на скалярную версию. Мы предполагаем, что оба x и y здесь правильно выровнены (только начинаются с кратного числа 16) и что n кратно 4, так как в противном случае потребуется некоторый установочный код для вычисления маски или для запуска скалярной версии. Мы также предполагаем, для простоты, что инструкции SIMD имеют возможность автоматически повторять скалярные операнды, как это может делать ARM NEON. [18] Если это не так, необходимо использовать "splat" (широковещательную рассылку), чтобы скопировать скалярный аргумент через регистр SIMD:
splatx4 v4 , a ; v4 = а, а, а, а
Затраченное время будет в основном таким же, как и для векторной реализации, y = mx + c
описанной выше.
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)
- иметь фазу очистки, которая, как и подготовительная часть, такая же большая и такая же сложная.
SIMD шириной восемь требует повторения алгоритма внутреннего цикла сначала с элементами SIMD шириной четыре, затем SIMD шириной две, затем одним (скалярным), с тестом и переходом между каждым из них, чтобы покрыть первый и последний оставшиеся SIMD. элементы (0 <= n <= 7).
Это более чем втрое увеличивает размер кода, а в крайних случаях приводит к увеличению количества инструкций на порядок ! Это может быть легко продемонстрировано путем компиляции iaxpy примера AVX-512 , используя параметры "-O3 -march=knl"
для GCC .
Со временем, по мере того, как ISA развивается, чтобы постоянно увеличивать производительность, это приводит к тому, что ISA Architects добавляют SIMD ширины 2, затем SIMD 4 ширины, затем 8 ширины и выше. Таким образом, мы начинаем понимать, почему AVX-512 существует в x86.
Без предсказания, чем шире ширина SIMD, тем хуже становятся проблемы, что приводит к массовому распространению опкодов, ухудшению производительности, дополнительному энергопотреблению и ненужной сложности программного обеспечения. [19]
С другой стороны, векторные процессоры предназначены для выполнения вычислений переменной длины для произвольного числа n и, следовательно, требуют очень небольшой настройки и никакой очистки. Даже по сравнению с теми SIMD ISA, у которых есть маски (но без setvl
инструкций), векторные процессоры создают гораздо более компактный код, потому что им не нужно выполнять явное вычисление маски для покрытия последних нескольких элементов (показано ниже).
Предоставленный SIMD
Предполагая гипотетический предиктированный (поддерживающий маску) SIMD ISA и снова предполагая, что инструкции SIMD могут справиться с несовпадающими данными, цикл инструкций будет выглядеть следующим образом:
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 * 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 называет эту технику программированием, не зависящим от длины вектора. [20]
Ниже представлен векторный ассемблер в стиле 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, даже если нет элементов для обработки, все равно не будет потраченного впустую кода очистки.
Пример векторной редукции
В этом примере мы начинаем с алгоритма, который включает редукцию. Как и в предыдущем примере, мы сначала показываем его в виде скалярных инструкций, затем SIMD и, наконец, векторных инструкций. Начнем с c :
void ( size_t n , int a , const int x []) { int y = 0 ; для ( size_t я = 0 ; я < п ; я ++ ) у + = х [ я ]; вернуть y ; }
Здесь аккумулятор (y) используется для суммирования всех значений в массиве x.
Скалярный ассемблер
Наша скалярная версия этого загрузит каждый из x, добавит его к y и зациклится:
установить y , 0 ; y инициализирован нулевым циклом: load32 r1 , x ; загрузить один 32- битный код add32 y , y , r1 ; y: = y + r1 addl x , x , $ 4 ; x: = x + 4 subl n , n , $ 1 ; n: = n - 1 jgz n , петля ; вернуться назад, если n> 0 out: ret y ; возвращает результат, y
Это очень просто. «y» начинается с нуля, 32-битные целые числа загружаются по одному в r1, добавляются к y, и адрес массива «x» перемещается к следующему элементу в массиве.
Сокращение SIMD
Вот здесь и начинаются проблемы. SIMD по своей задумке не может выполнять арифметические операции «межэлементные». Элемент 0 из одного SIMD регистр может быть добавлен элемент 0 из другого регистра, но элемент 0 может не быть добавлен к чему - либо другому , чем другой элемент 0. Это накладывает жесткие ограничения на возможные реализации. Предположим для простоты, что n равно 8:
addl r3 , x , $ 16 ; для 2-го 4, если x load32x4 v1 , x ; первые 4 из x load32x4 v2 , r3 ; 2-е 4 из x add32x4 v1 , v2 , v1 ; добавить 2 группы
На данный момент мы выполнили четыре добавления:
x[0]+x[4]
x[1]+x[5]
x[2]+x[6]
x[3]+x[7]
но из-за того, что SIMD не может добавлять, x[0]+x[1]
например, все быстро идет под откос, как и в общем случае использования SIMD для петель общего назначения. Подводя итог нашим четырем частичным результатам, можно использовать двухширокую SIMD, за которой следует одно скалярное сложение, чтобы окончательно получить ответ, но часто данные должны быть переданы из выделенных регистров SIMD до того, как может быть выполнено последнее скалярное вычисление. .
Даже с общим циклом (n не фиксировано) единственный способ использовать 4-разрядную SIMD - это использовать четыре отдельных «потока», каждый смещенный на четыре элемента. Наконец, необходимо суммировать четыре частичных результата. Другие методы включают перемешивание: в Интернете можно найти примеры для AVX-512 того, как выполнить «Горизонтальную сумму» [21] [22]
Помимо размера программы и сложности, при использовании вычислений с плавающей запятой возникает дополнительная потенциальная проблема: тот факт, что значения не суммируются в строгом порядке (четыре частичных результата), может привести к ошибкам округления.
Векторное уменьшение ISA
Наборы векторных инструкций имеют встроенные в ISA операции арифметической редукции . Если мы можем предположить, что n меньше или равно максимальной длине вектора, требуются только три инструкции:
setvl t0 , n # VL = t0 = min (MVL, n) vld32 v0 , x # загрузить вектор x vredadd32 y , v0 # уменьшить-добавить в y
Код, когда n больше максимальной длины вектора, не намного сложнее и похож на наш первый пример («IAXPY»).
set y , 0 vloop: setvl t0 , n # VL = t0 = min (MVL, n) vld32 v0 , x # загрузить вектор x vredadd32 y , y , v0 # добавить все x в y add x , t0 * 4 # продвинуть x by VL * 4 sub n , t0 # n - = VL (t0) bnez n , vloop # повторить, если n! = 0 ret y
По сравнению с SIMD простота алгоритма разительна. Опять же, как и в случае с примером IAXPY, алгоритм не зависит от длины (даже во встроенных реализациях, где максимальная длина вектора может быть только одна).
Аппаратные реализации могут, если они уверены, что будет получен правильный ответ, выполнить сокращение параллельно. Некоторые векторные ISA предлагают режим параллельного сокращения в качестве явной опции, когда программист знает, что любые потенциальные ошибки округления не имеют значения, а низкая задержка имеет решающее значение. [23]
Этот пример еще раз подчеркивает ключевое критическое фундаментальное различие между «истинными» векторными процессорами и этими процессорами SIMD, включая большинство коммерческих графических процессоров, которые «вдохновлены» функциями векторных процессоров.
Выводы из примеров
По сравнению с любым процессором SIMD, претендующим на роль векторного процессора, уменьшение размера программы на порядок просто шокирует. Однако этот уровень элегантности на уровне ISA имеет довольно высокую цену на аппаратном уровне:
- Из примера IAXPY мы видим, что в отличие от процессоров SIMD, которые могут упростить свое внутреннее оборудование, избегая работы с несогласованным доступом к памяти, векторный процессор не может избежать такого упрощения: пишутся алгоритмы, которые по своей сути зависят от успешной загрузки и сохранения векторов, независимо от выравнивания начала вектора.
- Хотя из примера сокращения мы видим, что, помимо инструкций перестановки , SIMD по определению полностью избегает межполосных операций (элемент 0 может быть добавлен только к другому элементу 0), векторные процессоры решают эту проблему напрямую. То, что программисты вынуждены делать программно (используя перемешивание и другие уловки, чтобы переставлять данные в нужную «полосу»), векторные процессоры должны делать аппаратно, автоматически.
В общем, есть выбор:
- сложное программное обеспечение и упрощенное оборудование (SIMD)
- упрощенное программное обеспечение и сложное оборудование (векторные процессоры)
Эти резкие различия - вот что отличает векторный процессор от процессора с SIMD.
Возможности векторного процессора
Если многие ISA SIMD «заимствуют» или «вдохновляются» приведенным ниже списком, типичные особенности хорошего векторного процессора: [24] [25] [26]
- Загрузка и хранение векторных данных - они по своей сути экономят на поиске в виртуальной памяти и предназначены для помещения данных в регистры с минимальными усилиями. Расширенные усовершенствования векторной загрузки / сохранения включают поддержку упаковки структуры , Fail-First, Gather-scatter , Indexed, Unit и Element.
- Маскированные операции - как теперь обычно используются в графических процессорах , маски предикатов позволяют выполнять параллельные конструкции if / then / else без ветвей (которые по своей природе скалярны)
- Сжатие и расширение - обычно с использованием битовой маски данные линейно сжимаются или расширяются (перераспределяются) в зависимости от того, установлены ли биты в маске или очищены, при этом всегда сохраняется последовательный порядок и никогда не дублируются значения (в отличие от Gather-Scatter aka permute) . Эти инструкции доступны в AVX-512
- Register Gather, Scatter (aka permute) [27] - менее ограничительный, более общий вариант темы 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 [28], хотя для произвольной ширины матрицы, которая не соответствует точному размеру SIMD, необходимы методы повторения данных, что приводит к расточительному использованию ресурсов регистрового файла. [29] Aspex ASP Linedancer имел механизм DMA с переупорядочиванием памяти 2D / 3D, который требовал значительных усилий для оптимального использования. [30] [31] NVidia предоставляет высокоуровневый Matrix CUDA API, хотя внутренние детали недоступны. [32] Наиболее ресурсоэффективным методом является переупорядочение доступа к линейным векторным данным на месте.
- Расширенные математические форматы - часто включают арифметику поля Галуа , но могут включать десятичную дробь с двоичным кодом или десятичную фиксированную точку, а также поддержку гораздо более крупных (произвольной точности) арифметических операций за счет поддержки параллельного переноса и переноса.
- Битовые манипуляции - включая векторизованные версии операций перестановки на уровне битов, вставку и извлечение битовых полей, операции центрифугирования, подсчет населения и многие другие .
Возможности векторной обработки на GPU
Поскольку многие приложения 3D- шейдеров нуждаются в тригонометрических операциях, а также в коротких векторах для общих операций (RGB, ARGB, XYZ, XYZW), в современных графических процессорах, помимо тех, что есть в векторных процессорах, обычно присутствует поддержка следующего:
- Субвекторы - элементы обычно могут содержать два, три или четыре субэлемента (vec2, vec3, vec4), где любой заданный бит маски предиката применяется ко всему вектору vec2 / 3/4, а не к элементам в субвекторе . Субвекторы также представлены в RISC-V RVV (называемом «LMUL»). [33] . Подвекторы являются важной составной частью спецификации Vulkan SPIR-V .
- Sub-vector Swizzle - он же « перетасовка дорожек », который позволяет проводить вычисления между субвекторами между элементами без необходимости дополнительных (дорогостоящих, расточительных) инструкций для перемещения субэлементов в правильные «дорожки» SIMD. Также сохраняет биты маски предиката. По сути, это мини-перестановка субвектора на лету , в значительной степени функциональная в двоичных файлах 3D-шейдеров, и достаточно важна, чтобы быть частью спецификации Vulkan SPIR-V . Broadcom Videocore IV использует терминологию «Lane Rotate » [34], тогда как остальная часть индустрии использует термин «swizzle» . [35]
- Трансцендентальные числа - тригонометрические операции, такие как синус , косинус и логарифм, очевидно, гораздо больше используются в 3D, чем во многих ресурсоемких рабочих нагрузках высокопроизводительных вычислений . Однако интересно то, что скорость намного важнее точности в 3D для графических процессоров, где вычисление координат пикселей просто не требует высокой точности. Спецификация Vulkan учитывает это и устанавливает удивительно низкие требования к точности, так что аппаратное обеспечение графического процессора может снизить энергопотребление. Концепция снижения точности там, где она просто не нужна, исследуется в расширении MIPS-3D .
Дополнительные функции включают Texture_mapping_unit, который иногда является отдельным блоком от основного процессора GPU. Также часто включаются инструкции интерполяции текстур и несколько других специальных инструкций, таких как векторная нормализация, а также скалярное произведение .
Дополнительную информацию и подсказки по функциям GPU Vector ISA можно найти, изучив спецификацию SPIR-V , [36] спецификацию Vulkan [37] и спецификацию OpenCL . [38] Эти API-интерфейсы были созданы Khronos Group такими участниками, как Intel, Google, AMD и NVIDIA, и, таким образом, дают представление о функциях, предоставляемых самыми быстрыми графическими процессорами в мире. Также может помочь переработанный набор инструкций графического процессора MALI Midgard. [39]
Сначала неисправность (или отказ)
В ARM SVE2 и RISC-V RVV введена концепция спекулятивных последовательных векторных нагрузок. ARM SVE2 имеет специальный регистр «Регистр первого сбоя» [40], где RVV изменяет (обрезает) длину вектора (VL). [41]
Основной принцип ffirst - попытаться выполнить большую последовательную векторную загрузку, но позволить оборудованию произвольно усечь фактический загруженный объем либо до суммы, которая будет успешной без возникновения ошибки памяти, либо просто до суммы (больше нуля), которая равна Самый удобный. Важным фактором является то, что последующие инструкции уведомляются или могут точно определять, сколько загрузок фактически выполнено, используя это количество только для выполнения работы с данными, которые были фактически загружены.
Сравните эту ситуацию с SIMD, который представляет собой фиксированную (негибкую) ширину загрузки и фиксированную ширину обработки данных, неспособную справиться с нагрузками, пересекающими границы страницы, и даже если бы они были, они неспособны адаптироваться к тому, что на самом деле удалось, но, как это ни парадоксально, если программа SIMD даже попытается заранее выяснить (в каждом внутреннем цикле, каждый раз), что может быть оптимально успешным, эти инструкции будут только снижать производительность, потому что они по необходимости будут частью критического внутреннего цикла.
Это начинает намекать на причину, по которой ffirst является таким инновационным, и лучше всего иллюстрируется memcpy или strcpy, когда они реализованы со стандартным 128-битным не-предикатным non-ffirst SIMD. Для IBM POWER9 количество оптимизированных вручную инструкций для реализации strncpy превышает 240. [42] Напротив, та же подпрограмма strncpy в оптимизированном вручную ассемблере RVV состоит всего из 22 инструкций. [43]
Вышеупомянутый пример SIMD потенциально может дать сбой и сбой в конце памяти из-за попыток чтения слишком большого количества значений: он также может вызвать значительное количество ошибок страницы или смещения из-за аналогичного пересечения границ. Напротив, предоставляя векторной архитектуре свободу решать, сколько элементов загружать, первая часть strncpy, если она начинается изначально на неоптимальной границе памяти, может возвращать достаточно нагрузок, так что при последующих итерациях цикла пакеты чтения векторизованной памяти оптимально согласованы с базовыми кэшами и механизмами виртуальной памяти. Кроме того, оборудование может решить использовать возможность завершения любой данной итерации цикла чтения памяти точно на границе страницы (избегая дорогостоящего второго поиска TLB), при спекулятивном выполнении, подготавливающем следующую страницу виртуальной памяти, в то время как данные все еще обрабатываются в текущем петля. Все это определяется оборудованием , а не самой программой. [44]
Производительность и ускорение
Пусть r - коэффициент векторной скорости, а f - коэффициент векторизации. Если время, затрачиваемое векторным блоком на добавление массива из 64 чисел, в 10 раз быстрее, чем у его эквивалентного скалярного аналога, r = 10. Кроме того, если общее количество операций в программе равно 100, из которых только 10 являются скалярными. (после векторизации), то f = 0,9, т.е. 90% работы выполняет векторный блок. Это следует за достижимым ускорением:
Таким образом, даже если производительность векторного блока очень высока () мы получаем ускорение меньше, чем , что предполагает, что отношение f имеет решающее значение для производительности. Это соотношение зависит от эффективности компиляции, например, от смежности элементов в памяти.
Программирование гетерогенных вычислительных архитектур
Были разработаны различные машины, включающие как традиционные процессоры, так и векторные процессоры, такие как Fujitsu AP1000 и AP3000. Программирование таких разнородных машин может быть трудным, поскольку разработка программ, наилучшим образом использующих характеристики различных процессоров, увеличивает нагрузку на программиста. Это увеличивает сложность кода и снижает переносимость кода, требуя, чтобы код, специфичный для оборудования, чередовался по всему коду приложения. [45] Балансировка нагрузки приложений между процессорами может быть проблематичной, особенно с учетом того, что они обычно имеют разные характеристики производительности. Существуют различные концептуальные модели для решения проблемы, например, с использованием языка координации и строительных блоков программы (программных библиотек или функций более высокого порядка). У каждого блока может быть своя собственная реализация для каждого типа процессора. Пользователи просто программируют, используя эти абстракции, а интеллектуальный компилятор выбирает лучшую реализацию на основе контекста. [46]
Смотрите также
- Архитектура SX
- Таксономия Дункана о конвейерных векторных процессорах
- ГПГПУ
- Вычислить ядро
- Потоковая обработка
- SIMD
- Автоматическая векторизация
- Цепочка (векторная обработка)
- Компьютер для работы с функциями
- RISC-V , открытый стандарт ISA со связанным расширением вектора переменной ширины .
- Бочковой процессор
- Блок тензорной обработки
- История суперкомпьютеров
- Архитектура суперкомпьютера
Внешние ссылки
- История развития параллельных вычислений (с 1955 по 1993 год)
- Векторные вычисления, прошлое, настоящее и будущее, Стив Скотт, Cray Inc.
- Руководство по NEC SX-Aurora ISA
- Ресурсы Broadcom VideoCore IV
- RISC-V Vectors, CS152, весна 2020 г.
- Справочное руководство по аппаратному обеспечению Cray-i, главы 1-3
- Справочное руководство по аппаратному обеспечению Cray-I 1977 г.
- Курс Университета Карнеги по графическим процессорам и векторным ISA
Рекомендации
- ↑ Малиновский, Б.Н. (1995). История компьютерных технологий в их лицах . Киев: Фирма "КИТ". ISBN 5-7707-6131-8.
- ^ [1]
- ^ [2]
- ^ [3]
- ^ Aspex Linedancer HD
- ^ Вертикальная исследовательская группа MIAOW
- ^ MIAOW GPU
- ^ Miyaoka, Y .; Choi, J .; Togawa, N .; Янагисава, М .; Оцуки Т. (2002). Алгоритм генерации аппаратных блоков для синтеза процессорного ядра с упакованными инструкциями типа SIMD . Азиатско-Тихоокеанская конференция по схемам и системам. 1 . п. 171-176. DOI : 10,1109 / APCCAS.2002.1114930 .
- ^ [4]
- ^ Обзор Cray
- ^ RISC-V RVV ISA
- ^ Обзор SX-Arora
- ^ [5]
- ^ Паттерсон, Дэвид А .; Хеннесси, Джон Л. (1998). Компьютерная организация и дизайн: аппаратно-программный интерфейс, страница 751-2 (2-е изд.). Морган Кауфманн. п. 751-2 . ISBN 155860491X.
- ^ [6]
- ^ Руководство программиста Videocore IV
- ^ Videocore IV QPU анализ Джеффа Буша
- ^ [7]
- ^ SIMD считается вредным
- ^ Учебное пособие по ARM SVE2
- ^ [8]
- ^ https://stackoverflow.com/questions/6996764/fastest-way-to-do-horizontal-sse-vector-sum-or-other-reduction/35270026#35270026
- ^ [9]
- ^ Обзор Cray
- ^ RISC-V RVV ISA
- ^ Обзор SX-Arora
- ^ Инструкции по сбору-разбросу регистра RVV
- ^ [10]
- ^ [11]
- ^ [12]
- ^ [13]
- ^ [14]
- ^ LMUL> 1 в RVV
- ^ Заброшенный патент США US20110227920-0096
- ^ Videocore IV QPU
- ^ [15]
- ^ [ https://www.khronos.org/registry/vulkan/ ]
- ^ [16]
- ^ [17]
- ^ Введение в ARM SVE2
- ^ Нагрузки RVV с первым отказом
- ^ ПАТЧ к libc6 для добавления оптимизированного strncpy POWER9
- ^ Пример RVV strncpy
- ^ Статья ARM SVE2 Н. Стивенса
- ^ Кунцман, DM; Кале, LV (2011). «Программирование гетерогенных систем». 2011 IEEE International Symposium on Parallel and Distributed Processing Workshops and 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