SIMT против SIMD: сходства и различия

16 Авг 2017

SIMT против SIMD: сходства и различия

Не секрет, что сильная сторона PC-платформ, определяющая их дол­го­ле­тие, — на­ли­чие огромного количества разнообразного программного обеспечения. Но, как известно, недостатки являются про­дол­же­ни­ем до­сто­инств: ком­па­нии Intel, ревниво оберегающей «ахиллесову пя­ту» сов­ме­сти­мос­ти, с каждым годом все сложнее кон­ку­ри­ро­вать с раз­ра­бот­чи­ка­ми аль­тер­на­тив­ных процессорных архитектур.


Для анализа сложившейся на сегодня расстановки сил, сравним подходы Intel и NVidia к организации вы­со­ко­про­из­во­ди­тель­ных параллельных вычислений:

Векторные расширения x86

Модель SIMD впервые была реализована в процессорах Intel Pentium с поддержкой технологии MMX. Повышение производительности основывается на векторизации вычислений, для этого несколько скалярных операндов упа­ко­вы­ва­ют­ся в одном векторном регистре. Размер вектора, а следовательно и количество операций, выполняемых одной инструкцией, определяется соотношением размерностей регистра и операнда. Современные процессоры Intel с поддержкой технологии AVX512, используют 512-битные регистры (ZMM0-ZMM31). Таким образом, за одну векторную инструкцию может быть обработано, например, восемь 64-битных чисел двойной точности, либо шест­над­цать 32-битных чисел одинарной точности.

Каждое обновление SIMD-расширений от Intel (MMX, SSE, AVX256, AVX512) несло не только количественные, но и качественные различия, включая организацию регистровых файлов и принципов кодирования инструкций, что приводило к необходимости редизайна компиляторов, приложений, фреймворков, системных процедур ОС. Не­смо­тря на совместимость расширенной системы команд с базовым x86-набором, для получения преимуществ от увеличения разрядности векторных регистров требуется основательная модификация и ре-оптимизация ПО.

Сильные стороны SIMD-архитектуры очевидны при обработке больших массивов информации по одинаковому ал­го­рит­му. Минусом можно считать накладные расходы (затраты процессорных тактов) на упаковку скалярных дан­ных в векторный регистр (gathering) и обратную распаковку (scattering), добавляемые в случае необходимости со­пря­же­ния скалярных и векторных фрагментов выполняемого кода. Ограниченная гибкость такого подхода ставит под сомнение дальнейшее увеличение разрядности векторных регистров.

Почему нельзя сложно сделать много x86-ядер

Многие операции, например умножение матриц, могут быть разделены на блоки, допускающие одновременное выполнение. Правило очевидно — если в алгоритме есть последовательность шагов, каждый из которых не ис­поль­зу­ет результат предыдущих, то действия могут быть выполнены параллельно.

Реализация этого принципа для многоядерного процессора Intel x86 на основе модели Simultaneous Multithreading (SMT) подразумевает выделение каждому вычислительному ядру своего «участка работы» в соответствии с выше описанным принципом. В чем же недостатки этой логичной и интуитивно понятной модели?

В ходе решения ряда задач, в частности для операций с векторами и матрицами большой размерности имеет мес­то обработка огромного количества данных по одинаковому алгоритму. При этом каждое из вычислительных ядер мультипроцессорной платформы выполняет один и тот же блок машинного кода, получая на вход разные данные. Это означает значительное количество «лишней работы», ведь в силу взаимной независимости вычислителей, каж­дый из них считывает, кэширует и декодирует одинаковые последовательности инструкций: акцентируем, в этом примере в параллельно выполняемых потоках различаются только данные.

Чтобы значительно упростить ядра, а значит увеличить их количество, размещаемое на кристалле процессора, мож­но использовать общую логику выборки и декодирования инструкций для группы вычислителей, тиражируя в со­от­вет­ствии с числом потоков только арифметико-логические устройства. Такое решение, оптимальное для ряда практических задач, в частности упомянутых выше операций линейной алгебры, неприемлемо при разработке x86-процессоров общего назначения, ведь система должна сохранять работоспособность и в общем случае, при котором на каждом из ядер выполняются различные процедуры. Забегая вперед отметим, что для разработчиков GPU аналогичный шаг позволителен.

Скалярный параллелизм от NVidia

В GPU, построенных на основе модели SIMT, процедуры обработки информации объединяются в группы, по­лу­чив­шие название Cooperative Thread Array (CTA). В каждой такой группе, называемой warp, один поток инструкций уп­рав­ля­ет обработкой нескольких (в типовом случае 32) потоков данных.

Блок-схема иерархической организации исполнительных блоков SIMT GPU
Блок-схема иерархической организации исполнительных блоков SIMT GPU

Иерархия вычислительных модулей GPU оптимизирована для ситуации, при которой все данные в пределах warp требуется обработать по общему алгоритму, это значит, что для управления группой из 32 потоков данных, можно использовать единственный поток инструкций, интерпретируемый одним уп­рав­ля­ю­щим блоком на группу из 32 арифметико-логических устройств.

Чтобы каждый из SIMT-потоков, выполняя строго одинаковый код, осуществлял доступ к своим данным, в ка­че­стве аргумента адресной арифметики используется индивидуальный номер потока. Уменьшение в 32 раза ко­ли­че­ства управляющих блоков в матрице вычислителей, означает рациональное использование транзисторов мик­ро­схе­мы, снижение потребления и возможность размещения большего количества ядер на кристалле.

Volta vs Pascal

В процессорах серии Volta к числу ресурсов, закрепленных за каждым потоком данных, добавлены счетчик команд (Program Counter) и стек вызовов (Call Stack). Ранее, в процессорах серии Pascal, указанные объекты были общими для груп­пы из 32 потоков.

Сравнение моделей обработки ветвлений для GPU Pascal и Volta
Сравнение моделей обработки ветвлений для GPU Pascal и Volta

Изменения можно расценивать как децентрализацию логики ветвлений в пределах Cooperative Thread Array. Это позволяет организовать условную передачу управления, индивидуально осуществляемую в каждом потоке, на ос­но­ва­нии содержимого обрабатываемых данных.

Вместо послесловия

Переходя от противопоставления векторных и скалярных архитектур к анализу системы команд NVidia PTX — Parallel Thread Execution можно убедиться в том, что технологии SIMD и SIMT не являются вза­и­мо­ис­клю­ча­ю­щи­ми и могут применяться совместно. Акцентируем внимание на упоминаемом в сопровождающей документации тер­ми­не PTX Virtual Machine. Он означает существенное различие в использовании языка ассемблера для процессоров x86 CPU и NVidia GPU:

  • В первом случае программист имеет дело с «настоящей» системой команд — мнемоника каждой ин­струк­ции со­от­вет­ст­ву­ет машинному коду, аппаратно интерпретируемому процессором.
  • Во втором случае, между набором операций, описанным ассемблерным исходным текстом и системой ко­манд GPU, создается промежуточный уровень абстракции, как правило, силами оптимизирующего ком­пи­ля­тора; налицо компромисс, где на одной чаше весов находятся требования портируемости и снижения тру­до­ем­ко­сти разработки, на другой — возможность «ручной» низкоуровневой оптимизации критических секций кода.
Теги: