7994420702;horizontal

Параллельные вычислительные процессоры NVIDIA: настоящее и будущее, часть 5

Дуальный планировщик варпов  

Как уже говорилось выше, в мультипроцессоре теперь 32 исполнительных устройства, которые в терминологии CUDA называются Scalar Processor Core, или CUDA Core. В процессорной терминологии, этому больше соответствует functional unit с небольшой оберткой. То есть, мультипроцессор может выполнить целый варп за такт. Но это неудобно, потому что остальная часть мультипроцессора работает на половинной частоте, по сравнению с частотой «скалярных процессорных ядер». Чтобы разрешить ситуацию, планировщик варпов был сделан двойным, он сразу отправляет на исполнение два варпа, каждый на 16 исполнительных устройств. Таким образом, варп из 32 одинаковых инструкций выполняется за два такта функциональных устройств и один такт остального ядра. Но два варпа, выполняющие инструкцию c данными типа double, не могут быть исполнены вместе, так как инструкции double выполняются два такта или двумя функциональными устройствами. То есть, так полный варп из 32 double-инструкций выполнится за один «длинный» такт.

Не предполагается, что такая конструкция как-то поможет ускорить дивергентные ветвления внутри одного варпа. Просто варп с такими ветвлениями будет исполняться дольше, пропорционально количеству ветвлений, в то время как другие варпы будут идти параллельно.

С применением нового техпроцесса, стало возможным увеличить размер локальной памяти мультипроцессора и сделать небольшой L1-кэш, а так же разместить на кристалле общий для всех мультипроцессоров L2-кэш размером 768 Кб.

Является ли это отходом от подхода, реализованного в предыдущих графических процессорах, которые обходятся почти без кэшей? Может, лучше было и этот кэш пустить на мультипроцессоры? Нет, он занимает мало места, а пользы может принести много.

L1-кэш  

Он служит, в первую очередь, для буферизации. Просто, даже если нить запрашивает из глобальной памяти 4 байта, транзакция все равно осуществляется минимум с 64 байтами. И весьма вероятно, что загруженные данные могут понадобиться вскоре этой или другим нитям. Эти загруженные блоки данных можно пока сохранить. С такой логикой, раз уж мы скопировали из памяти избыточные данные, пока оставим, вдруг пригодятся.

Теперь, размер локальной памяти мультипроцессора составляет 64 Кб и её можно сконфигурировать программно, оставить 16 Кб разделяемой и 48 Кб нового L1-кэша. Это полезно для старых CUDA-программ, которые не знают о том, что объем разделяемой памяти, доступной блоку нитей, увеличился. Зато они могут выиграть от большего размера кэша. Или сконфигурировать локальную память, в пропорции 48 Кб разделяемой, 16 Кб кэша. То есть, дать возможность программе самой решить, что загружать в память мультипроцессора. Но это тоже будет способствовать росту производительности старых CUDA-программ, так как большее количество блоков и нитей сможет одновременно выполняться на мультипроцессоре. Допустим, если раньше один блок из 256 нитей требовал 16 Кб разделяемой памяти и на мультипроцессоре мог выполняться только один блок, то сейчас — 3, так как им всем хватит памяти.

Также, L1-кэш очень поможет для быстрого свопа, то есть, временного хранения регистров. Сейчас, при программировании CUDA-приложения, желательно использовать как можно меньше регистров мультипроцессора, чтобы на одном мультипроцессоре можно было запустить больше нитей. И, крайне нежелательно, временно сбрасывать содержимое регистров в медленную глобальную память. На это иногда жалуются CUDA-программисты, что им не хватает регистров. А если хватает, то запускается меньше нитей, которые меньше скрывают различные задержки. Приходится думать, как программу реализовать с меньшим количеством временных регистров. Интересная оптимизационная задача конечно. Немного необычно: найти такой нетребовательный алгоритм, иногда бывает похоже на задачу из олимпиады по информатике.

L2–кэш  

Первая функция общего кэша второго уровня — это радикально ускорить и упростить синхронизацию всех исполняющихся нитей. Нити, выполняющейся на одном мультипроцессоре, не могут видеть содержимое L1–кэшей других мультипроцессоров, но когда данные сбрасываются в L2–кэш, например, принудительными синхронизирующими инструкциями, они сразу становятся видимыми для всех. Раньше, для синхронизации между блоками использовалась сверхмедленная, глобальная память. Это сильно упрощает написание сложных CUDA-программ.

И, конечно, L2 выступает неким общим пулом загружаемых из глобальной памяти данных. GT200 имеет 256 Кб кэша второго уровня для текстурной памяти на все мультипроцессоры, сейчас размер кэша утроился до 768 Кб. И он стал полноценным, а не только для чтения данных.

Удобно, конечно, для контроллеров памяти, оперирующих широкими кусками данных, наполнять строчки L1-; L2-кэшей. Именно в ширине интерфейса глобальной памяти кроется необходимость иметь достаточно большой промежуточный пул и несколько отойти от концепции тратить всю площадь кристалла на исполнительные устройства. Представьте, вы заказываете из магазина товар, но в вашем распоряжении самосвал, он привозит не только товар, но и все, что рядом лежит. Раньше оно выбрасывалось, а теперь сохраняется в кэше. И конечно, некоторые задачи с объемом данных, сравнимым с размером кэша, получат очень сильный прирост. Но никакой кэш, тем более, меньше мегабайта размером, не решит проблему доступности данных в случае, близкого к случайному, доступа десятков тысяч одновременно исполняющихся на мультипроцессоре нитей. Для этой цели служит большое количество активных нитей на мультипроцессоре. Кстати, максимальное количество одновременно исполняющихся нитей на мультипроцессоре также возросло.

Поддержка C++  

Новая версия архитектуры CUDA включает полную поддержку C++, виртуальных функций, указателей на функции и конструкций try–catch. Это расширяет область применения решений на основе архитектуры Fermi и сильно облегчает портирование многих существующих приложений на GPU. Но главное, что многие программисты просто любят программировать на С++, даже если он не очень нужен для решения конкретной задачи. Очень характерно, что часто, обсуждение архитектуры «Ферми» моментально выливается в спор С vs С++. Чтож, скоро сторонники и противники разных подходов к программированию получат ещё одно поле битвы. На чем лучше программировать Fermi? С или С++?

Но на языках Си свет клином не сошёлся и, благодаря поддержке указателей на функции, стала возможной поддержка большого количества самых разнообразных языков программирования. Причем, не ориентированных на высокую скорость исполнения написанных на них программ.

Изначально, CUDA предназначалась для высокопроизводительных, во многом оптимизированных приложений, но многие программы выгоднее писать без оглядки на железо, а потом смотреть, как процессоры «страдают», выполняя тяжёлый код и выбирать лучшее для своей задачи. Параллельное программирование проникает в массы и, с полной поддержкой указателей, появилась возможность просто запускать на GPU широкий класс параллельных программ. Fermi и в этом случае может оказаться конкурентоспособным, т.к. такие программы и на классическом CPU будут отчаянно медленно исполняться. И на каждое обращение к памяти у них будет море инструкций обращения к собственным регистрам и так далее.

Да, для универсализации потребовалось объединить в одном адресном пространстве всю, доступную отдельной нити, память. Собственную память мультипроцессора и видимую глобальную память. Это также важно для заявленной поддержки операторов new и delete, то есть, выделения памяти прямо из CUDA-программы, исполняющейся на CUDA-устройстве. О чем раньше и подумать было нельзя. Очень интересно будет посмотреть, как в реальности будет работать собственный менеджер памяти.

Программные улучшения  

Компания NVIDIA заявляет об увеличении скорости переключения задач, поскольку на GPU может выполняться несколько CUDA-приложений. Но более важно то, что теперь одновременно может выполняться несколько CUDA-функций одного приложения. Потому, что одна может не загрузить все устройство. И это делает возможным плотнее загрузить поддерживающий CUDA GPU при запуске нескольких задач подряд. Так как программа, приближаясь к своему завершению, может работать лишь на нескольких мультипроцессорах, в то время как остальные уже освободились.

Исполнение нескольких функций может помочь скрыть длительное время передачи данных по шине PCI-Express. Чтобы GPU не останавливался в ожидании передачи данных. Может быть, даже одну задачу выгодно будет делить на несколько меньших, чтобы первые блоки уже начинали считать, пока подгружаются остальные данные.

Заключение  

Последний пункт особенно четко демонстрирует «суперкомпьютерный» характер новой архитектуры. Можно смело сказать, что мы получаем настоящий суперкомпьютер на столе. Страшно подумать, что их ещё можно установить несколько в одной системе и объединить вместе несколько таких компьютеров. Получается целый вычислительный фрактал. Перечислим его: нить — полуварп (16) — варп (2*16) — блок нитей (2*16*8) — мультипроцессор (2*16*8*4) — GPU (2*16*8*4*30) — multiGPU (2*16*8*4*30*4) — узел из 8 компьютеров (2*16*8*4*30*4*8)= ~ пол миллиона нитей и десять тысяч операций за одну миллиардную секунды. И дешевле обычного сервера. Может, правда, запретить «Ферми» к продаже, а то какие-нибудь террористы рассчитают что–то вроде ядерного оружия?

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

Ссылки  

  • NVIDIA's GT200: Inside a Parallel Processor
    Обзор чипа GT200, с точки зрения внутренней микроархитектуры.
  • Inside Fermi: NVIDIA's HPC Push
    Превью-обсуждение микроархитектуры «Ферми», возможных вариантов внутренней реализации. Правда, обзоры написаны чисто с точки зрения аппаратного обеспечения, автор обзоров предпочитает считать нити «векторными линиями». Хотя, с точки зрения программирования, они вполне самостоятельны.
  • NVIDIA Fermi Compute Architecture Whitepaper
    Описание новой архитектуры «Ферми» от разработчика.
  • CUDA home
    Красочный список программ, использующих CUDA, а также различных работ, посвященных CUDA. Есть возможность выбрать программу из интересуемой области и посмотреть, какую производительность можно ожидать, а также что, в принципе, можно реализовать с помощью CUDA. Но не все представленные там программы полностью используют возможности CUDA, что-то можно написать более оптимально. Среди представленных приложений есть и программа автора, игра AntiPlanet2.
  • CUDA-программа автора (дополнительная ссылка)
    Трехмерное графическое приложение, работающее в реальном времени и использующее CUDA для вычислений. На момент выхода данной статьи, CUDA-версия имеет бета статус. Функция, которая реализована на CUDA, получает ускорение примерно в три раза (ускорение зависит от настроек программы и время копирования данных из GPU не учитывается, в финальной версии данные копироваться из GPU не будут, так как это графическое приложение и можно воспользоваться прямым доступом к буферу экрана). Сравнивается GTX275 и Lynnfield 2.8 ГГц. Впрочем, CUDA-функцию, вероятно, можно ещё оптимизировать. В то время как CPU-версия полностью оптимизирована.
  • CUDA SDK
    CUDA SDK с примерами использовании CUDA в самых различных областях от самой NVIDIA. Они (примеры) представлены как в исходных кодах, так и в виде готовых исполняемых файлов. Также, можно выбрать пример из нужной области и оценить прирост производительности. Есть примеры с графикой и с научными или экономическими вычислениями.
    Для ознакомления, лучше всего выбирать примеры из знакомой области, чтобы можно было понять, что можно получить, в сравнении с известными CPU-реализациями. Так как прирост от использования CUDA, сильно зависит от конкретного алгоритма.
19 ноября 2009 года
20 сентября 2010 года






Похожие статьи

  • Проблемы и преимущества Fermi

    Выход представителей нового поколения графических процессоров NVIDIA несколько раз откладывался, в итоге первые GeForce и Tesla на новой архитектуре вышли урезанными, относительно первоначально заявленных спецификаций. Они так же неприятно удивили довольно высоким уровнем энергопотребления. Что послужило причиной задержек? И стоило ли ждать? Какие особенные архитектурные инновации выделяют Fermi и делают его уникальным?

  • Pentium4 производства AMD

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

  • Краткий анализ архитектуры NVIDIA Fermi

    Основным практическим воплощением новой архитектуры NVIDIA Fermi должен стать графический процессор GT300, который придёт на замену поколению GT200. Следует отметить, что этот графический процессор содержит в себе много нововведений концептуального характера, количество и качество которых позволяет судить о нём как о ключевом продукте компании, определяющем развитие графических процессоров на последующие два-три года.

  • Развитие вычислений на GPU: преимущества архитектуры Fermi

    Прошло всего три года со дня выхода в свет GPU c поддержкой CUDA, но за это время не только производительность видеокарт NVIDIA выросла на порядок, но и программная архитектура приобрела практически завершенный вид.

  • Проблемы трассировки лучей — из будущего в реальное время

    В данной статье рассмотрен перспективный метод формирования изображения, так называемый метод трассировки лучей, или ray tracing. Описаны принцип работы метода и приведены примеры использования. Также затронуты аспекты его применения в реальных приложениях, рассмотрены плюсы и минусы использования данного метода на современных системах.