Ouvi dizer que se as declarações devem ser evitadas em shaders, porque ambas as partes serão executadas e o errado será descartado (o que prejudica o desempenho).
Ainda existe um problema no DirectX 10? Alguém me disse que nele apenas o ramo certo será executado.
Para a ilustração, tenho o código:
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;
}
Existe outra maneira de torná-lo mais rápido?
Se sim, como faz?
Os dois ramos são parecidos, a única diferença são os valores de "constantes" ( y1, y2, b1, b2
são iguais para todos os pixels no Pixel Shader).
Respostas:
Muitas regras para shaders de otimização micro são as mesmas que para CPUs tradicionais com extensões de vetor. Aqui estão algumas dicas:
test
,lerp
/mix
)É verdade que as filiais são mais baratas no hardware moderno do que costumavam ser, mas ainda é melhor evitá-las, se possível. Usando as funções swizzling e test, você pode reescrever seu shader sem testes:
Usar
step
elerp
é um idioma muito comum para escolher entre dois valores.fonte
Geralmente está tudo bem. Os sombreadores serão executados em grupos de vértices ou pixels (diferentes fornecedores têm uma terminologia diferente para isso, então estou mantendo isso distante) e se todos os vértices ou pixels de um grupo seguirem o mesmo caminho, o custo da ramificação será insignificante.
Você também precisa confiar no compilador de sombreador. O código HLSL que você escreve não deve ser visto como uma representação direta do bytecode ou mesmo da montagem que será compilada, e o compilador é perfeitamente livre para convertê-lo em algo equivalente, mas evita a ramificação (por exemplo, um lerp às vezes pode ser uma conversão preferida). Por outro lado, se o compilador determinar que a execução de uma ramificação é realmente o caminho mais rápido, ela será compilada em uma ramificação. Visualizar a montagem gerada no PIX ou uma ferramenta semelhante pode ser muito útil aqui.
Finalmente, a velha sabedoria ainda se mantém aqui - analise-a, determine se realmente é um problema de desempenho para você e resolva-o então, não antes. Assumindo que algo pode ser um problema de desempenho e agir de acordo com essa suposição, haverá um risco enorme de problemas maiores posteriormente.
fonte
Citação do link / artigo postado por Robert Rouhani:
Como mh01 sugeriu ("Visualizar o assembly gerado no PIX ou uma ferramenta semelhante pode ser muito útil aqui."), Você deve usar uma ferramenta de compilador para examinar a saída. Na minha experiência, a ferramenta Cg da nVidia (a Cg ainda é amplamente usada hoje por causa de suas capacidades de plataforma cruzada) deu uma ilustração perfeita do comportamento mencionado nos fragmentos de códigos de condição de parágrafo dos . Portanto, independentemente do valor do acionador, ambas as ramificações foram avaliadas por fragmento e, somente no final, a correta foi colocada no registro de saída. No entanto, o tempo de computação foi desperdiçado. Naquela época, eu pensava que a ramificação ajudaria o desempenho, principalmente porque todos gemas (predicação) da GPU naquele shader que contava com um valor uniforme para decidir sobre o ramo certo - isso não aconteceu como pretendido. Portanto, uma grande ressalva aqui (por exemplo, evite as trepadeiras - possivelmente a maior fonte do inferno).
fonte
Se você ainda não está tendo problemas de desempenho, tudo bem. O custo para comparação com uma constante ainda é extremamente barato. Aqui está uma boa leitura sobre a ramificação da GPU: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter34.html
Independentemente disso, aqui está um trecho de código que será pré-formado muito pior que a instrução if (e é muito menos legível / sustentável), mas ainda assim se livra dela:
Note que estou assumindo que x é limitado ao intervalo
[0, 1]
. Isso não funcionará se x> = 2 ou x <0.O que esse snippet faz é converter x em um
0
ou1
e multiplicar o errado por 0 e o outro por 1.fonte
if(x<0.5)
o valor parafx
deve serround(x)
oufloor(x + 0.5)
.Existem várias instruções capazes de fazer condições sem ramificação;
Além de alguns operadores lógicos;
fonte: http://theorangeduck.com/page/avoiding-shader-conditionals
fonte