2012-04-14 2 views
17

Меня интересует информация о скорости sin() и cos() в Open GL Shader Language.Скорость функции cos() и sin() в шейдерах GLSL?

GLSL Specification Document указывает, что:

Встроенные функции в основном делятся на три категории:

  • ...
  • ...
  • Они представляют собой операции графического оборудования скорее всего, ускорится в какой-то момент. Функции тригонометрии относятся к категории .

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

Что значит «современные графические процессоры» обеспечивают аппаратное ускорение для 'sin()' и 'cos()'? " Если он работает на графическом процессоре, можно сказать, что аппаратное ускорение. В любом случае лучше всего попробовать и профилировать его, так как тактовые циклы на графическом процессоре несколько бессмысленны без дополнительного контекста относительно того, что вы делаете. Даже между разными картами одного и того же поставщика могут быть различия в количестве исполнительных блоков, поэтому циклы только сообщают вам часть истории. – user1118321

+0

С этими графическими процессорами я думаю, что у вас будет самое быстрое время выполнения этих тригонометрических функций. Интересный вопрос ... –

+0

Как указано в [this] (http://stackoverflow.com/questions/10111898/glsl-relative-to-each-other-how-expensive-are-operations-like-multiply-divide) и [this] (http://stackoverflow.com/questions/8415251/performance-of-different-cg-glsl-hlsl-functions), этот вопрос по существу неопровержимо. Особое использование 'sin' может стоить * ничего *, в зависимости от того, где вы его используете, и аппаратного обеспечения. –

ответ

16

Например, в моем приложении, это будет очень часто для аргумент равен 0. Таким образом, делает что-то вроде этого имеют смысл:

No.

Ваш компилятор будет делать один двух вещей.

  1. Он выдаст фактическую условную ветку. В наилучшем возможном случае, если 0 - это когерентное значение локально (такое, что группы шейдеров будут часто попадать в 0 или ненулевые вместе), то вы можете может получить более высокую производительность.
  2. Он будет оценивать с обеих сторон условия и сохраняет только результат для правильного одного из них. В этом случае вы ничего не получили.

В общем, не стоит использовать условную логику для танцев вокруг небольшой производительности, как это. Это должно быть действительно большим, чтобы быть полезным, например, discard или что-то в этом роде.

Также обратите внимание, что эквивалентность с плавающей точкой вряд ли будет работать. Нет, если вы фактически не передаете шейдеру единый или вершинный атрибут, содержащий ровно 0,0. Даже интерполирование между 0 и отличным от нуля, вероятно, никогда не даст ровно 0 для любого фрагмента.

+1

Я бы фактически передал значение 0.0 шейдеру в виде вершины атрибут. Но хороший момент, если бы я не тестировал, что значение будет небольшим эпсилон от 0, вероятно, будет необходимо. Но точка зрения на это, вероятно, не стоит в первую очередь. – ulmangt

+0

В зависимости от объема работы, которую должен выполнять каждый шейдер, вы можете выиграть, имея два варианта: один, где вы знаете, что он равен нулю, а другой - там, где это не так. Но переключение шейдеров не из дешевых, так что это зависит от рабочей нагрузки. – Robinson

+1

@NicolBolas И, действительно, после прочтения вашего ответа и запоминания некоторых из моих CUDA, я думаю, что есть третий вариант: шейдер может оценить первую сторону условия для потоков, где 'rotation == 0', в то время как остальные блокируют (или noop), затем оцените вторую сторону в первом блоке. Который, очевидно, был бы плохим. Хотя это предполагает, что шейдеры оценивают аналогично ядрам CUDA. – ulmangt

2

Не уверен, что это отвечает на ваш вопрос, но очень сложно рассказать вам, сколько часов/слотов требуется для обучения, поскольку это очень сильно зависит от GPU. Обычно это один цикл. Но даже если нет, компилятор может изменить порядок выполнения команд, чтобы скрыть истинную стоимость. Конечно, медленнее использовать поиск текстур для sin/cos, поскольку он должен выполнять инструкции.

+0

Я не вижу никаких упоминаний о sincos() в спецификации http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.40.05.pdf, каково фактическое имя функции? Это расширение? – ulmangt

+0

Мои извинения, на самом деле я думаю, что это может быть только D3D, и даже тогда я думаю, что компилятор неявно генерирует для него инструкцию sin и cos. – Robinson

+0

FWIW, есть команда FRB Fragment 'SCS ', которая возвращает синус (input.x) в х-компоненте и cos (input.x) в y-компоненте. – user1118321

5

Вам придется протестировать это самостоятельно, но я уверен, что разветвление в шейдере намного дороже, чем расчеты или cos. Компиляторы GLSL довольно хорошо разбираются в оптимизации шейдеров, поэтому беспокоиться об этом преждевременно. Если позже вы обнаружите, что через всю вашу программу ваши шейдеры являются узким местом, тогда вы можете беспокоиться об оптимизации этого.

Если вы хотите взглянуть на код сборки вашего шейдера для конкретной платформы, я бы порекомендовал AMD GPU ShaderAnalyzer.

+0

"при ** ** код сборки". Для шейдеров нет сборки ** ** **. Он меняется с платформы на платформу. И даже от версии драйвера до версии драйвера. –

+0

Спасибо, исправил. –

+0

Ветвь на униформе bool, вероятно, будет бесплатной. Я использовал эту технику в таком типе ситуации, когда это было уместно. –

6

Это хороший вопрос. Я тоже удивился этому.

Google'd linkscos и sin являются одноцилиндровыми на обычных картах с 2005 года или около того.

1

Посмотрите, сколько грехов вы можете получить в одном шейдере подряд, по сравнению с math.abs, frac, ect ... Я думаю, что gtx 470 может обрабатывать 200 функций sin для фрагмента без проблем, кадр будет 10 процентов медленнее, чем пустой шейдер. это очень быстро, вы можете отправить результаты. Это будет хорошим показателем вычислительной эффективности.

-2

Компилятор оценивает обе ветви, что делает условия довольно дорогими. Если вы используете как sin, так и cos в вашем шейдере, вы можете рассчитать только sin (a) и cos (a) = sqrt (1.0 - sin (a)), так как sin (x) * sin (x) + cos (x) * cos (x) всегда 1.0

+1

sin (x) + cos (x) обычно не 1,0. Вероятно, вы думаете о том, что sin (x) * sin (x) + cos (x) * cos (x) равно 1,0. Хотя эта идентификация может использоваться для вычисления одного значения из другого, это включает в себя квадратный корень, который, вероятно, так же дорог, как и вычисление значения. Так что это не очень полезно. Кроме того, современные графические процессоры обычно не оценивают обе ветви, пока значения условий одинаковы для всех значений фрагмента, которые обрабатываются вместе. –

+0

Да, я думал о cos^2 (x) + sin^2 (x) = 1 из теоремы Пифагора. Виноват. –

Смежные вопросы