Автор: Сem Cebenoyan
Перевод:А. А. Лунтовская
Источник: C. Cebenoyan — Graphics Pipeline Performance. — GPU Gems: programming techniques for high‑performance graphics and general‑purpose computation (Matt Pharr ed), 2005, http://developer.download.nvidia.com/books/HTML/gpugems/gpugems_ch28.html.
За последние несколько лет конвейеры рендеринга с аппаратным ускорением резко увеличились по сложности, принеся с собой все более сложные характеристики. Повышение производительности ранее применялось для обозначения простого сокращения внутренних циклов процессора в визуализации, сейчас стало циклом определения узких мест и систематической борьбы с ними. Этот цикл идентификации и оптимизации имеет фундаментальное значение для настройки гетерогенных многопроцессорных систем; определяющая идея заключается в том, что конвейер (pipeline), по определению, не быстрее, чем его самый медленный участок. Таким образом, в то время как преждевременная сфокусированная оптимизация в однопроцессорной системе может привести к минимальному приросту производительности, в многопроцессорных системах такая оптимизация очень часто приводит к нулевым выгодам.
То есть, если мы прилагаем все усилия по оптимизации графики и видим нулевое повышение производительности, это не очень хорошо. Цель этой статьи — держать вас от этого подальше.
Конвейер, на самом высоком уровне, можно разбить на две части: центральный и графический процессор. Хотя CPU оптимизация является важной частью оптимизации приложения, он не будет в центре внимания этой главы, потому что большая часть этой оптимизации не имеет ничего общего с графическим конвейером. Рисунок 1 показывает, что в ГПУ (буквально, процессоре видеокарты, GPU), существует множество функциональных блоков, работающих параллельно, которые по большей части действуют как отдельные процессоры специального назначения, а также количество мест, где может возникнуть узкое место. К ним относятся вершины и индексы выборки, фрагменты теней и растровых операций (ROP).
Оптимизация без надлежащей идентификации узких мест является причиной многих впустую потраченных усилий в области развития, и поэтому мы должны формализовать процесс на следующие фундаментальные идентификации и оптимизации цикла:
Поиск узких мест является залогом успеха в оптимизации, потому что она позволяет принимать разумные решения о сосредоточении усилий вашей фактической оптимизации. На рисунке 2 показана блок‑схема последовательности шагов, необходимых для точного нахождения узкого места в приложении. Обратите внимание, что мы начинаем с заднего конца конвейера, с буфера кадра операций (так называемые растровые операции) и заканчиваем в процессоре. Отметим также, что любой примитив (обычно в виде треугольника) по определению имеет одно узкое место, а на протяжении кадра узкое место, скорее всего, изменяется. Таким образом, изменение нагрузки на более чем одной стадии в конвейере часто влияет на производительность. Например, низкополигональный скайбокс часто связан с затенением фрагмента или доступом к буферу фреймов, скелетный меш, который отображает только несколько пикселей на экране часто связан с процессором или обработкой вершин. По этой причине это часто помогает варьировать нагрузки на объект‑на‑объект или материала‑на‑материал.
Для каждого этапа конвейера, отметим также графический процессор, к которому он привязан (то есть, основной или памяти). Эта информация полезна в сочетании с такими инструментами, как PowerStrip (Тайвань EnTech 2003), которая позволяет сократить соответствующие тактовые частоты и наблюдать изменения производительности в приложениях.
Самый конец графического конвейера, растровые операции (которые часто называют ROP), несет ответственность за чтение и запись глубины, сравнение глубины, чтение и письма цвета и альфа‑смешивание и тестирование. Как вы можете видеть, большая часть нагрузки ROP налагается на доступную полосу пропускания буфера кадра.
Лучший способ проверить,обладает ли ваше приложение достаточной пропускной способностью буфера кадра, это изменить биты глубины цвета или глубины буферов, или обоих. Если, сокращая битовую глубину от 32‑разрядной на 16‑бит значительно улучшает производительность, то работа приложения, безусловно, связана с пропускной способностью буфера кадра.
Полоса пропускания буфера кадра является функцией часов GPU памяти, так что изменения часов памяти еще один метод определения этого узкого места.
Текстура потребляет пропускную способность в любое время, когда запрос текстуры выходит за рамки памяти. Хотя современные графические процессоры уже поддерживают текстурные кэши, чтобы минимизировать посторонние запросы к памяти, они, очевидно, все еще происходят и потребляют достаточное количество пропускной способности памяти.
Изменение форматов текстур может быть сложнее, чем модификации форматов буфера кадра, как мы делали при проверке ROP; вместо этого, мы рекомендуем изменить эффективный размер текстуры с помощью большого количества положительных MIPMAP преобразования уровня в детализации (LOD). Это делает доступ к текстурным выборкам на очень грубых уровнях MIPMAP пирамиды, которая эффективно снижает размер текстуры. Если эта модификация позволяет значительно улучшить производительность, проблемы связаны с пропускной способностью текстур.
Фрагментные шейдеры относятся к фактической стоимости генерации фрагментов с соответствующими
значениями цвета и глубины. Это стоимость запуска пиксельных шейдеров
или
фрагментных шейдеров
. Обратите внимание, что фрагментный шейдинг и пропускная способность
буфера кадра часто объединены под заголовком скорость заполнения, потому что оба являются
функцией от разрешения экрана. Тем не менее, они являются двумя отдельными этапами в конвейере,
и способность выделить разницу между двумя этими этапами имеет решающее значение для эффективной
оптимизации.
До появления высоко программируемых графических процессоров обработки фрагментов, фрагментный шейдинг редко был обязателен. Часто это была пропускная способность буфера кадра, которая вызвала неизбежную корреляцию между разрешением экрана и производительности. Это маятник сейчас начинают качаться к фрагментному шейдингу, однако, вновь обретенная гибкость позволяет разработчикам тратить большое количество циклов для создания причудливые пикселей.
Первый шаг в определении, является ли фрагментный шейдинг узким местом, это изменение разрешения. Поскольку мы уже исключили пропускную способность буфера кадра с помощью перебора различных глубин буфера кадра в битах, регулируя разрешение мы изменяем производительность, виновником чегоявляется, скорее всего, фрагментные шейдеры. Дополнительный подход будет изменять длину ваших программ фрагментов и смотреть, влияет ли это на производительность.
Скорость фрагментного затнени является функцией часов графического процессора.
Этап конвейера рендеринга по преобразованию вершин отвечает за принятие на вход набора атрибутов вершины (например, нормалей вершин, текстурных координат, и так далее) и производить набор атрибутов, пригодных для отсечения и растеризации (например, однородная позиция в клип пространстве, результаты освещения вершин, текстурные координаты, и т. д.). Естественно, производительность в этой стадии является функцией проделанной работы над каждой вершины, вместе с числом обрабатываемых вершин.
С программируемыми преобразованиями, изменяя длину вашей программы обработки вершин, определение, является ли обработка вершин вашим узким местом, становится простым делом. Если изменения производительности, вы вершина обработки связаны. Если вы хотите добавить инструкции, будьте осторожны, чтобы добавить те, которые на самом деле выполняют значимую работу; в противном случае, команды могут не быть оптимизированы компилятором. Например, операции, которые относятся к постоянным регистрам (например, добавление постоянного регистра, который имеет значение, равное нулю), часто не могут быть оптимизированы, потому что компилятор, как правило, не знают значение постоянной в программе компиляции.
Если вы используете фиксированные функции преобразования, это немного сложнее. Попробуйте изменить нагрузку, изменяя вершины работы, такие как зеркального освещения или текстурные координаты.
Скорость обработки вершин является функцией основных часов графического процессора.
Вершины и индексы обрабатываются в ГПУ на первом этапе конвейера рендеринга. Производительность обработки вершин и индексов может варьироваться в зависимости от того, где фактические расположены вершины и индексы. Они, как правило,располагаются либо в системной памяти, что означает, что они будут переданы в ГПУ по шине, такой как AGP или PCI Express, либо в локальной памяти буфера кадров. Часто особенно на платформах ПК, это решение возложено на драйвер устройства, а не приложения, хотя современные графические интерфейсы позволяют приложениям обеспечивать намек на использование, чтобы помочь драйверу выбрать правильный тип памяти.
Определение, является ли вершина или индекс узким местом в вашем приложении, возможно за счет изменения размера формата вершина.
Производитльность выборки вершин и индексов зависит от скорости AGP / PCI Express, если данные размещены в системной памяти; и от зависит от частоты памяти, если данные размещены в локальной памяти буфера кадров.
Если ни один из этих тестов не влияет на вашу производительность значительно, производительноть, скорее всего, зависит от ЦП.
Многие приложения зависимы от ЦП, иногда по уважительной причине, например, из‑за сложной физики или AI, а иногда и из‑за плохого управления ресурсами. Если вы обнаружили, что ваше приложение зависит от ЦП, попробуйте следующие предложения по снижению работы процессора в конвейере рендеринга.
Каждый раз, когда вы выполняете синхронную работу, что требует доступа к ресурсу GPU, есть возможность, что графический конвейер будет сильно терять скорость, что приведет к перегрузке как ЦП, так и циклов ГПУ. Циклы центрального процессора будут расходоваться впустую, потому что процессор должен находиться в цикле(очень глубоком), ожидая конвейер графисекого процессора, чтобы вернуться к запрошенному ресурсу. Затем теряются циклы ГПУ, поскольку конвейер сидит сложа руки, ожидая ресурс.
Эта блокировка может произойти каждый раз, когда вы блокируете или читаете с поверхности, на которую ранее производили рендеринг; обращаетесь к поверхности, с которой считывает ГПУ, например, текстуры или буфер вершин. В общем, вы должны избегать доступа к ресурсу, используя графический процессор во время рендеринга.
С увеличением мощности и программируемости современных графических процессоров,
становится сложнее извлкать из машины каждый бит производительности.
Если ваша цель заключается в повышении производительности медленного приложения или поиске областей,
где вы можете улучшить качество изображения бесплатно
, требуется глубокое понимание внутренней работы графического конвейера.
Конвейер графического процессора продолжает развиваться, но фундаментальные идеи оптимизации остаются неизменными:
сначала определить узкие места, изменяя нагрузку или вычислительную мощность каждого блока;
затем систематически атаковать те узкие места, используя ваше понимание о том, как каждая единица конвейера рендеринга ведет себя.
1. EnTech Taiwan. 2003. Web site. http://www.entechtaiwan.com. Information on the PowerStrip package is available here.
2. Wloka, Matthias. 2003. Batch, Batch, Batch: What Does It Really Mean?
Presentation at Game Developers Conference 2003. Available online at http://developer.nvidia.com/docs/IO/8230/BatchBatchBatch.pdf Specific information can be found at the following Web addresses.
3. NVIDIA. 2003. Developer Web site. http://developer.nvidia.com. On this site, you can find tools that will help you with performance tuning.