Скорость функции cos() и sin() в шейдерах GLSL?
Мне интересна информация о скорости sin()
и cos()
в Open GL Shader Language.
Документ спецификации GLSL указывает, что:
Встроенные функции в основном делятся на три категории:
- ...
- ...
- Они представляют собой графическое аппаратное обеспечение, которое может ускориться в какой-то момент. Функции тригонометрии попадают в это категория.
EDIT:
Как уже отмечалось, подсчет тактовых циклов отдельных операций, таких как sin()
и cos()
, на самом деле не отражает всю историю производительности.
Итак, чтобы уточнить мой вопрос, меня действительно интересует, стоит ли оптимизировать проводы sin()
и cos()
для обычных случаев.
Например, в моем приложении для аргумента будет очень распространено 0
. Так что-то вроде этого имеет смысл:
float sina, cosa;
if ( rotation == 0 )
{
sina = 0;
cosa = 1;
}
else
{
sina = sin( rotation );
cosa = cos( rotation );
}
Или компилятор GLSL
или реализации sin()
и cos()
позаботится об оптимизации для меня?
Ответы
Ответ 1
Например, в моем приложении для аргумента будет очень распространено 0. Так что-то вроде этого имеет смысл:
Нет.
Ваш компилятор сделает одно из двух.
- Он выдает фактическую условную ветвь. В наилучшем возможном случае, если 0 - это когерентное значение локально (такое, что группы шейдеров будут часто попадать в 0 или ненулевые вместе), вы можете получить улучшенную производительность.
- Он оценит обе стороны условия и сохранит результат только для одного из них. В этом случае вы ничего не получили.
В целом, не рекомендуется использовать условную логику, чтобы танцевать вокруг небольшой производительности, как это. Это должно быть действительно большим, чтобы быть полезным, например, discard
или что-то в этом роде.
Также обратите внимание, что эквивалентность с плавающей запятой вряд ли будет работать. Нет, если вы фактически не передаете шейдеру единый или вершинный атрибут, содержащий ровно 0,0. Даже интерполирование между 0 и отличным от нуля, вероятно, никогда не даст ровно 0 для любого фрагмента.
Ответ 2
Это хороший вопрос. Я тоже задавался этим вопросом.
Ссылки Google говорят, что cos
и sin
являются однотактными на обычных карточках с 2005 года или около того.
Ответ 3
Вам придется проверить это самостоятельно, но я уверен, что разветвление в шейдере намного дороже, чем вычисление sin
или cos
. Компиляторы GLSL довольно хорошо разбираются в оптимизации шейдеров, поэтому беспокоиться об этом преждевременно. Если позже вы обнаружите, что через всю вашу программу ваши шейдеры являются узким местом, вы можете беспокоиться об оптимизации этого.
Если вы хотите взглянуть на код сборки вашего шейдера для конкретной платформы, я бы рекомендовал AMD GPU ShaderAnalyzer.
Ответ 4
Не уверен, что это отвечает на ваш вопрос, но очень сложно рассказать вам, сколько часов/слотов требуется для команды, поскольку это очень сильно зависит от GPU. Обычно это один цикл. Но даже если нет, компилятор может изменить порядок выполнения команд, чтобы скрыть истинную стоимость. Конечно, медленнее использовать поиск текстуры для sin/cos, поскольку он должен выполнять инструкции.
Ответ 5
Посмотрите, сколько грехов вы можете получить в одном шейдере подряд, по сравнению с math.abs, frac, ect... Я думаю, что gtx 470 может обрабатывать 200 функций sin для каждого фрагмента без проблем, кадр будет 10 процентов медленнее, чем пустой шейдер. это очень быстро, вы можете отправить результаты. Это будет хорошим показателем вычислительной эффективности.
Ответ 6
Компилятор оценивает обе ветки, что делает условия довольно дорогими. Если вы используете как sin, так и cos в вашем шейдере, вы можете рассчитать только sin (a) и cos (a) = sqrt (1.0 - sin (a)), так как sin (x) * sin (x) + cos (x) * cos (x) всегда 1.0