Я слышал, что если в шейдерах следует избегать операторов, потому что обе части операторов будут выполнены, а неправильные будут отброшены (что вредит производительности).
Это все еще проблема в DirectX 10? Кто-то сказал мне, что в этом будет выполнена только правая ветка.
Для иллюстрации у меня есть код:
float y1 = 5; float y2 = 6; float b1 = 2; float b2 = 3;
if(x>0.5){
x = 10 * y1 + b1;
}else{
x = 10 * y2 + b2;
}
Есть ли другой способ сделать это быстрее?
Если так, как это сделать?
Обе ветви выглядят одинаково, единственное отличие - это значения «констант» ( y1, y2, b1, b2
одинаковые для всех пикселей в Pixel Shader).
Ответы:
Многие правила для микрооптимизирующих шейдеров такие же, как и для традиционных процессоров с векторными расширениями. Вот несколько советов:
test
,lerp
/mix
)Это правда, что на современном оборудовании филиалы дешевле, чем раньше, но все же лучше их избегать, если это возможно. Используя функции Swizzling и Test, вы можете переписать свой шейдер без тестов:
Использование
step
иlerp
является очень распространенной идиомой для выбора между двумя значениями.источник
Вообще все нормально. Шейдеры будут выполняться в группах вершин или пикселей (разные поставщики имеют разную терминологию для них, поэтому я держусь в стороне от этого), и если все вершины или пиксели в группе идут по одному и тому же пути, тогда стоимость ветвления незначительна.
Вы также должны доверять шейдерному компилятору. Код HLSL, который вы пишете, не должен рассматриваться как прямое представление байт-кода или даже сборки, в которую он будет компилироваться, и компилятор совершенно свободно может преобразовать его во что-то, что эквивалентно, но избегает ветвления (например, иногда может быть lerp). предпочтительное преобразование). С другой стороны, если компилятор определит, что выполнение ветвления на самом деле является более быстрым путем, он скомпилирует его в ветвь. Просмотр сгенерированной сборки в PIX или подобном инструменте может быть очень полезен здесь.
Наконец, старая мудрость все еще здесь - профилируйте ее, определите, действительно ли это проблема с производительностью для вас, и решайте ее тогда, а не раньше. Предполагая, что что-то может быть проблемой производительности, и действуя в соответствии с этим предположением, вы в дальнейшем будете подвергаться огромному риску возникновения более серьезных проблем.
источник
Цитата из ссылки / статьи, опубликованной Робертом Рухани:
Как предположил mh01 («Просмотр сгенерированной сборки в PIX или подобном инструменте может быть очень полезным здесь.»), Вы должны использовать инструмент компилятора для проверки вывода. По моему опыту, инструмент Cg от nVidia (Cg по-прежнему широко используется сегодня из-за его кроссплатформенных возможностей) дал прекрасную иллюстрацию поведения, упомянутого в параграфе кодов состояния драгоценных камней GPU (предикация) . Таким образом, независимо от значения триггера, обе ветви оценивались для каждого фрагмента, и только в конце правильная была помещена в выходной реестр. Тем не менее, время вычислений было потрачено впустую. Тогда я думал, что ветвление поможет производительности, особенно потому, что всефрагменты в этом шейдере полагались на единое значение, чтобы выбрать правильную ветвь - это не произошло, как предполагалось. Итак, главное предостережение здесь (например, избегать убершадеров - возможно, самый большой источник разветвляющегося ада).
источник
Если у вас нет проблем с производительностью, это нормально. Стоимость для сравнения с константой все еще чрезвычайно дешева. Вот хорошее прочтение о ветвлении графического процессора: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter34.html
В любом случае, вот фрагмент кода, который будет преформироваться намного хуже, чем оператор if (и гораздо менее читабелен / поддерживаем), но все же избавится от него:
Обратите внимание, что я делаю предположение, что x ограничен диапазоном
[0, 1]
. Это не будет работать, если x> = 2 или x <0.То, что делает этот фрагмент, конвертирует x в либо
0
или,1
и умножает неправильное на 0, а другое на 1.источник
if(x<0.5)
значение дляfx
должно бытьround(x)
илиfloor(x + 0.5)
.Есть несколько инструкций, способных выполнять условия без ветвления;
Плюс несколько логических операторов;
источник: http://theorangeduck.com/page/avoiding-shader-conditionals
источник