Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Суперкомпьютеры и системы. Мультипроцессоры. Учебное пособие

.pdf
Скачиваний:
1
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
сти – идеально соответствовала принципам архитектуры ОКМД. Поэто­му в видеоакселераторах стали реализовываться специализированные потоковые процессоры, работавшие вначале по фиксированным заши­тым алгоритмам обработки графической информации. Затем с целью обеспечения большей степени гибкости в видеоакселераторах были реа­лизованы возможности загрузки программ обработки из центрального процессора. До середины 2000-х годов эти программы разрабатывались на узкоспециализированных языках обработки графической информа­ции. При этом производительность видеоакселераторов быстро росла и начала превосходить (и существенно) производительность центральных процессоров, правда только на ограниченном круге задач.
И, наконец, в 2006 году компания NVIDIA преодолела устоявший­ся к тому моменту психологический барьер и представила технологию обработки неграфической информации на графическом процессоре под названием CUDA – Compute Unified Device Architecture.
Технология CUDA основывается на аппаратной ОКМД-структуре, изображенной на рис. 4.2, и представляет собой синтаксическое рас­ширение языков С/С++ при помощи дополнительных спецификаторов (ключевых слов) переменных и функций, а также библиотек функций и механизма запуска ядер.
Графический процессор обычно содержит несколько (от единиц до десятков в зависимости от модели устройства) вычислителей – муль­типроцессоров в терминологии NVIDIA . Мультипроцессоры работают под управлением аппаратно реализованного планировщика блоков по­токов. На рис. 4.3 для примера показано размещение основных элемен­тов графического процессора NVIDIA с микроархитектурой Fermi. Этой микроархитектуре предшествовала Tesla, далее появились Kepler, Maxwell и Volta. Переход от одной микроархитектуры к другой сопро­вождается увеличением производительности чипа и уменьшением от­носительных энергозатрат на каждый выполняемый гига- (или тера-) флоп.
Мультипроцессор архитектуры Fermi содержит следующее:
планировщик пучков потоков (варпов в терминологии NVIDIA );
кэш-память для хранения инструкций исполняемого ядра;
устройство управления, выбирающее и декодирующее инструкции;
набор арифметико-логических устройств (потоковых процессо-
ров в терминологии NVIDIA , их количество также зависит от модели устройства и колеблется от 16 до 192) для обработки целых чисел и чисел с плавающей запятой одинарной точности в режиме ОКМД;
51
Рис. 4.2. ОКМД-структура графического процессора NVIDIA
Рис. 4.3. Основные элементы графического процессора NVIDIA
52
несколько арифметико-логических устройств для обработки чи- сел с плавающей запятой с двойной точностью;
регистровый файл (быстрая память на кристалле, распределяе- мая между потоками блока);
разделяемую (доступную всем потокам блока) быструю память.
Кроме совокупности мультипроцессоров кристалл графического процессора содержит общие для них элементы:
уже упоминавшийся планировщик блоков потоков;
несколько контроллеров глобальной памяти устройства, находя-
щейся вне чипа и обладающей существенно большим объемом, но зна­чительно меньшим (в 300–500 раз) быстродействием по сравнению с внутрикристалльной памятью;
L2-кэши глобальной (отсутствуют в архитектуре Tesla), текстур- ной и константной памяти.
Рис. 4.4. Микроархитектура ядра Cayman компании AMD
53
Видеоадаптеры основного конкурента фирмы NVIDIA – компа­нии AMD – развивались в аналогичном направлении, что также при­вело к созданию высокопроизводительных графических процессоров. На рис. 4.4 показана укрупненная структура ядра микроархитектуры Cayman, используемой в нескольких моделях высокопроизводитель­ных графических процессоров серий Radeon HD 69хх и FirePro. Ком­поненту гетерогенной системы Compute Unit (мультипроцессору в терминологии NVIDIA) здесь соответствует SIMD Engine, содержа­щий большое количество (320…384) потоковых процессоров.
Совокупность ОКМД Engine управляется командным процессором (Command Processor), генератором потоков управления (Thread Generator) и устройством их распределения (Ultra-Threaded Dispatch Processor). В отличие от планировщиков блоков и ворпов, управляю­щих мультипроцессорами как единицами вычислительного контекста в графических процессорах фирмы NVIDIA, эти компоненты чипа Cayman способны асинхронно распределять между потоковыми про­цессорами всю совокупность задач, сформированных драйвером для графического процессора. Затраты времени на переключения потоко­вых процессоров даже между различными ядрами в этой технологии оказываются незначительными.
Выборку данных для потоковых процессоров выполняет Fetch Unit, связанный с основной памятью через кэши L1 и L2 объемом 8 кБ и 128 кБ соответственно. Локальная память Local Data Store объемом 32 килобайта соответствует регистровому файлу в устройствах NVidia.
4.2. ВЫЧИСЛИТЕЛЬНЫЕ АКСЕЛЕРАТОРЫ
Вычислительные акселераторы – это специализированные парал­лельные процессоры, изначально ориентированные на обеспечение высокой производительности при относительно небольших аппарат­ных затратах. К вычислительным акселераторам относится Intel Xeon Phi – специальный ускоритель для научных расчетов, имеющий тера­флопсную производительность (один триллион операций с плавающей точкой в секунду). В отличие от графических процессоров (NVIDIA GPGPU, AMD Radeon и др), Intel Xeon Phi основан на архитектуре процессора x86, его структура изображена на рис. 4.5.
Чип содержит:
высокопроизводительную широкую кольцевую шину для связи всех компонентов, находящихся внутри чипа;
54
Рис. 4.5. Структура вычислительного акселератора Intel Xeon Phi
большое количество (от 60) процессорных ядер, каждое из кото- рых имеет собственный когерентный L2 кэш;
восемь контроллеров GDDR MC, которые обслуживают 16 кана- лов памяти типа GDDR5;
отдельный компонент реализует клиентскую логику PCI Express для подключения акселератора к центральному процессору.
Intel Xeon Phi выполнен в виде платы расширения стандарта PCI Express на основе многоядерного процессорного чипа (от 60 ядер x86) с памятью стандарта GDDR5. Плата имеет разъем PCI Express x16, ее энергопотребление достигает 300 Вт. Каждое ядро содержит когерент­ный кэш второго уровня объемом 512 кБ и имеет доступ к своей соб­ственной оперативной памяти, объем которой варьируется от модели к модели.
Xeon Phi – реализация архитектуры Intel MIC (Many Inegrated Core или «большое количество ядер в одной микросхеме»), позволяющей ис­пользовать стандартный исходный код на языках C, C++ и FORTRAN и компилировать его для исполнения как на Xeon Phi, так и на любых компьютерах с процессорами Intel Xeon.
55
4.3. ПРОБЛЕМЫ ПРОГРАММИРОВАНИЯ ГРАФИЧЕСКИХ ПРОЦЕССОРОВ
И ВЫЧИСЛИТЕЛЬНЫХ АКСЕЛЕРАТОРОВ
Использование графических процессоров и вычислительных акселе­раторов в составе и суперкомпьютеров, и обычных персональных ком­пьютеров сопряжено с возникновением ряда проблем и трудностей [15]. Они обусловлены принципиально иным соотношением последователь­ного / параллельного в вычислениях, чем в любых ранее существовавших параллельных системах. Возможность запуска десятков и сотен миллио­нов параллельных потоков вычислений без необходимости непрерывно координировать их работу радикально изменяют сами принципы про­граммирования. Неоднородность вычислительных средств, содержащих центральный многоядерный процессор и акселератор на основе ОКМД­принципов, приводит к необходимости решения задачи распределения нагрузки на этапе разработки алгоритма решения прикладной задачи. По­стоянно протекающие процессы интеграции разнотипных компьютерных компонентов в состав чипов центральных процессоров требуют тща­тельного анализа существующих тенденций при выборе направлений развития средств программирования акселераторов.
Первая созданная для поддержки неграфических высилений на гра­фических процессорах технология программирования CUDA является проприетарным продуктом и может быть использована только для устройств NVIDIA. Cложность написания качественного кода на CUDA­расширении языков C и C++ привела к созданию ряда других техноло­гий программирования акселераторов, в том числе OpenCL, C++ AMP и OpenACC.
OpenCL является непроприетарным двойником CUDA и пользуется поддержкой многих крупных компаний. Он не ограничен только чипами NVIDIA, но поддерживает графические процессоры AMD, многоядер­ные CPU, Intel Xeon Phi, цифровые сигнальные процессоры и програм­мируемые логические матрицы, что делает его переносимым. Однако, так же как и CUDA, он очень низкоуровневый: требует от программиста непосредственного управления перемещением данных между централь­ным и графическим процессорами, явного определения мест хранения переменных в иерархии памяти и ручной реализации параллелизма в коде.
Технология C++ Accelerated Massive Parallelism (C++ AMP) имеет более высокий уровень. Она позволяет описывать параллельные алго-
56
ритмы уже на самом С++ и скрывает весь низкоуровневый код от про­граммиста. Оператор «for each» инкапсулирует параллельный код. Технология C++ AMP привязана к операционным системам Windows; пока ещё не поддерживает, как это умеет OpenCL, ускорители разных архитектур и имеет слишком большие накладные расходы на запуск приложения.
OpenACC – это еще более высокоуровневый подход к программиро­ванию ускорителей, который позволяет программистам снабдить код ди­рективами, сообщив тем самым компилятору, какие части кода требуется ускорить, выгружая их в графический процессор. Идея схожа с тем, как OpenMP используется для распараллеливания CPU-программ. Предпри­нимаются усилия к объединению этих двух подходов. OpenACC находит­ся на этапе созревания и в настоящее время поддерживается только не­многими компиляторами.
Чтобы понять, как в дальнейшем будет развиваться область про­граммирования аппаратных ускорителей, стоит изучить, как подобный процесс протекал в прошлом с другими аппаратными ускорителями. К примеру, микропроцессоры ранних персональных компьютеров «не умели» выполнять операции с плавающей точкой. В составе таких ком­пьютеров обычно имелся дополнительный компонент – сопроцессор, выполняющий вычисления с плавающей точкой. Позже он был объеди­нен на одном кристалле с центральным процессором и сейчас является его неотъемлемой частью. Процессор и сопроцессор имеют лишь разные регистры и арифметико-логические устройства. Более поздние ОКМД­расширения процессоров (MMX, SSE, AltiVec и AVX) не выпускались в виде отдельных чипов, но сейчас они полностью интегрированы в про­цессорные чипы. Точно так же, как и инструкции с плавающей точкой, ОКМД-инструкции выполняются на отдельных АЛУ и с использовани­ем собственных регистров.
Удивительно, но два этих типа инструкций существенно различа­ются, с точки зрения программиста. Вещественные типы и операции с ними были давно стандартизированы (IEEE 754) и сегодня использу­ются повсеместно. Они доступны в высокоуровневых языках програм­мирования через обычные арифметические операции и встроенные вещественные типы данных: 32 бита для вещественных чисел одинар­ной точности и 64 бита для двойной точности. Однако не существует никаких стандартов для ОКМД-инструкций, и само их наличие в про­цессоре, как правило, скрыто от программиста. Использование ОКМД­инструкций для ускорения вычислений путем векторизации по умол-
57
чанию делегировано компиляторам, а их разработчики далеко не все­гда используют эти возможности. Программисты, желающие явно ис­пользовать ОКМД-инструкции, должны обращаться к компилятору при помощи специальных некроссплатформенных макросов.
В силу того что высокая производительность GPU и MIC ускорите­лей обусловлена их ОКМД-природой, весьма вероятно, что их развитие пойдет путем предыдущих ОКМД-расширителей. Еще одно сходство с ОКМД – ключевая особенность технологии CUDA, сделавшая ее успешной. Она состоит в том, что CUDA скрывает ОКМД-сущность, характерную для графических процессоров, и позволяет программисту мыслить в терминах потоков, оперирующих скалярными данными, в то время как графический процессор работает в терминах варпов (warp), оперирующих векторами. Поэтому вполне вероятно, что ОКМД-ускори­тели в конечном итоге тоже будут перенесены на кристалл процессора.
Такие примеры уже известны. Некоторые ускорители уже были совмещены на кристалле с традиционными процессорами – это AMD APU (используется в Xbox One), процессоры Intel с интегрированной HD-графикой и Tegra SoC от NVIDIA. Однако ОКМД-ускорители останутся, вероятно, отдельно программируемым компонентом просто потому, что трудно объединить их с традиционным процессорным яд­ром до такой же степени, как это было сделано с математическим со­процессором и с ОКМД-расширениями. В конце концов ОКМД-уско­рители именно потому такие быстрые, параллельные и энергоэффектив­ные, что построены на основе отличных от CPU архитектурных реше­ний, таких как некогерентый кэш, совершенно другая реализация кон­вейера, память GDDR5, на порядок большее количество регистров, лег­ковесная многопоточность. Следовательно, сложность запуска кода на акселераторах по-прежнему останется. Скорость обмена данными меж­ду CPU и ОКМД-акселераторами будет расти, но все-таки останется уз­ким местом.
Необходимость явного управления процессами обмена данными между устройствами является существенным источником ошибок и трудностей. Для небольших алгоритмов часто бывает, что приходится писать больше кода для того, чтобы организовать обмен данными, чем для вычислений. Устранение этого недостатка является одним из ос­новных преимуществ высокоуровневых подходов к программирова­нию, таких как C++ AMP и OpenACC. Даже низкоуровневые реализа­ции направлены на решение этой проблемы. К примеру, хорошо отла­женный и унифицированный доступ к памяти – это одно из основных
58
улучшений, которые реализуются в последних версиях CUDA, OpenCL и аппаратных решениях NVIDIA GPU. И тем не менее для достижения хорошей производительности обычно требуется помощь программиста даже в таких высокоуровневых решениях, как OpenACC.
К сожалению, все упрощения, предлагаемые такими подходами, могут оказаться только частным решением. Учитывая, что будущие процессоры станут близки к сегодняшним (малым) суперкомпьютерам, вполне вероятно, что в них будет больше ядер, чем их сможет обслу­живать общая память. Весьма вероятно также, что на каждом кристал­ле будет реализовано несколько кластеров из потоковых ядер, а каж­дый кластер будет иметь собственную память. Кластеры будут связаны друг с другом сетью, выполненной на том же кристалле и использую­щей протокол, подобный MPI. Примером движения в этом направле­нии могут служить процессоры SW26010, на которых построен китай­ский суперкомпьютер TaihuLight, рассматриваемый во второй части пособия. Процессорные чипы будут содержать множество кластеров с собственной памятью. Каждый кластер будет состоять из многих ядер, при этом необязательно все ядра будут функционально идентичными. Каждое многопоточное ядро будет состоять из множества вычисли­тельных звеньев (т. е. функциональных блоков или АЛУ) и каждое вы­числительное звено будет выполнять ОКМД-инструкции.
Это поднимает крайне важный вопрос, как программировать такие устройства. Вполне возможно, что это будет развитием современных решений для многоядерных CPU, их ОКМД-расширителей и существу­ющих на данный момент акселераторов. Происходит это на трех уров­нях:
библиотеки;
инструменты автоматизации;
«сделай сам».
Библиотеки – простейший для прикладного программиста подход, основанный на вызове функций из библиотек, которая была ранее со­здана и оптимизирована для ускорителя. Если большинство вычисле­ний программы может быть выполнено путем вызова библиотечных функций, то применение этого подхода будет вполне оправдано. Уже сейчас существует большое количество таких библиотек, например, CuBLAS, CuFFT, CuDNN для графических процессоров NVidia.
В технологиях C++ AMP и OpenACC используется другой подход – инструменты автоматизации. При таком подходе тяжелая работа по организации взаимодействия центрального процессора и акселератора
59
перекладывается на компилятор. Качество решения им этой задачи зависит от качества и сложности существующих программных ин­струментов и, как было сказано, часто требует вмешательства про­граммиста. Тем не менее большинство программистов могут довольно быстро достичь хороших результатов, используя этот подход, который не ограничен только применением предопределенных функций из биб­лиотек.
Наконец, подход «сделай сам» используется в CUDA и OpenCL. Он дает программисту полный контроль над доступом почти ко всем ре­сурсам ускорителя. При хорошей реализации результирующий код обычно превосходит по производительности любой из двух предыду­щих. Но это дается путем значительных усилий на изучение языка и акселератора и написание большого количество дополнительного кода и обеспечивает больший простор для возможных ошибок. Всяческие усовершенствования сред разработки и отладки могут смягчить все эти трудности, но только до определенной степени. А значит, этот подход полезен в первую очередь для экспертов, т. е. тех специалистов, кото­рые занимаются разработкой методов двух предыдущих подходов.
Поскольку OpenCL предлагает практически все решения, пред­ставленные в CUDA, не является проприетарным и поддерживает раз­ные аппаратные решения, эта технология или производные от нее ре­шения, вероятнее всего, станут преобладающими в области програм­мирования вычислительных акселераторов подобно тому, как MPI стал стандартом де-факто в программировании систем с распределенной памятью.
60