Desempenho de loop em um sombreador


11

Gostaria de saber qual é a melhor maneira de integrar uma função de loop dinâmico em um shader?

Primeiro, parece que matrizes dinâmicas não são possíveis. Então, é melhor criar uma matriz de tamanho máximo e preencher apenas uma parte dela ou definir matrizes com tamanhos predefinidos?

Então, qual é a melhor maneira de iterar nessa matriz?

É melhor usar um loop desenrolado ou dinâmico para algo entre 4 a 128 iterações? Também vi que é possível desenrolá-lo para um número máximo predefinido de iterações e pará-lo com uma condição como if (i == myCurrentMaximumIterationNumber).


2
O que você está tentando fazer com a matriz e o loop? Estou perguntando, porque isso de alguma forma parece um problema XY para mim. Como a melhor maneira de usar condições e loops na GPU é evitar usá-las, talvez haja maneiras ainda melhores em vez de usar matrizes e loops no seu caso.
Nero

Estou implementando um efeito de dispersão de subsolo no espaço da tela que atualmente funciona. Mas tenho algumas dúvidas sobre o modo como uso o kernel de acordo com o desempenho. Eu escolhi fazer um tamanho máximo de matriz e preencher apenas uma parte e usar um loop dinâmico com um número dinâmico de iteração relacionado ao conteúdo da matriz atualmente usado. Eu acho que há coisas para fazer ou saber ao programar shaders de acordo com as performances, por exemplo. E, na minha opinião, loops é um tópico de desempenho comum que pode seguir algumas regras e talvez "boas práticas", mas não encontrei nenhuma resposta boa sobre isso.
MAT

Respostas:


6

Os compiladores de shader são extremamente agressivos quanto ao desenrolamento, pois o HW inicial muitas vezes não tinha controle de fluxo e o custo em HW mais recente pode variar. Se você tem uma referência em que está testando ativamente e uma variedade de hardware relevante, tente as coisas para ver o que acontece. Seu loop dinâmico é mais passível de intervenção do desenvolvedor do que um loop estático - mas deixá-lo para o compilador ainda é um bom conselho, a menos que você tenha um benchmark disponível. Com uma referência, a exploração vale a pena (e é divertida).

BTW, a maior perda com um loop dinâmico em uma GPU é que "threads" individuais em uma frente de onda / distorção terminam em momentos diferentes. Os threads que param mais tarde forçam todos os que terminam cedo a executar NOPs.

Os loops aninhados devem ser cuidadosamente pensados: Implementei um decodificador de entropia baseado em bloco que codifica execuções de zeros (para JPEG como compactação). A implementação natural era decodificar as execuções em um loop interno apertado - o que significava frequentemente que apenas um thread estava progredindo; achatando o loop e testando explicitamente em cada thread se atualmente estava decodificando uma execução ou não, mantive todos os threads ativos através do loop de comprimento fixo (os blocos decodificados tinham o mesmo tamanho). Se os threads fossem como threads de CPU, a mudança teria sido terrível, mas na GPU em que eu estava executando, obtive um aumento de 6 vezes no desempenho (o que ainda era terrível - não havia blocos suficientes para manter a GPU ocupada - mas foi uma prova de conceito).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.