Melhorando seu jogo com o Burst 1.7

TIM JONES / UNITY TECHNOLOGIESSenior Software Engineer
Mar 14, 2022|9 Min
Melhorando seu jogo com o Burst 1.7
Esta página da Web foi automaticamente traduzida para sua conveniência. Não podemos garantir a precisão ou a confiabilidade do conteúdo traduzido. Se tiver dúvidas sobre a precisão do conteúdo traduzido, consulte a versão oficial em inglês da página da Web.

A versão mais recente do pacote Burst vem com alguns grandes aprimoramentos no tempo de iteração e no Burst Inspector. Nesta postagem, veremos o que mudou e como nossa tecnologia de compilador de C# de alto desempenho (HPC#) agora pode ajudá-lo a melhorar o desempenho em todas as plataformas com ainda mais facilidade.

Embora nossa pilha de tecnologia DOTS aproveite o Burst para fornecer código altamente otimizado, o Burst é um pacote autônomo, disponível no Package Manager para Unity 2019.4 ou mais recente. Milhares de seus projetos em todas as principais plataformas de desktop, console e dispositivos móveis já estão aproveitando o Burst.

Iteração no tempo de iteração

Nas versões anteriores do Burst, fizemos avanços significativos para melhorar a experiência cotidiana de trabalho com o Burst. No Burst 1.7, demos continuidade a essa tendência, concentrando-nos em melhorar o tempo de iteração. O que queremos dizer com tempo de iteração? Estamos nos referindo ao "loop interno" do desenvolvimento: você faz uma alteração em um script C#, volta para o Editor, aguarda a conclusão da compilação do script, aguarda a conclusão da compilação do Burst e entra no modo Play para testar a alteração.

No Burst 1.7, reduzimos drasticamente o tempo de espera pelo Burst, para o cenário comum de fazer algumas alterações no código do jogo e testá-lo no modo Play. A compilação Burst agora ocorre mais cedo no pipeline (imediatamente após o pipeline de compilação de scripts ter concluído a compilação de assemblies .NET), de modo que, em muitos casos, ela é concluída no momento em que o código resultante precisa ser executado. Em vez de compilar cada ponto de entrada do Burst separadamente, como acontecia nas versões anteriores do Burst, os pontos de entrada do Burst (por exemplo, um trabalho ou ponteiro de função) agora são agrupados para melhorar o rendimento do compilador e reduzir o número de bibliotecas que o Editor precisa carregar.

O Burst 1.7 também inclui um grande aprimoramento no desempenho da Direct Call. Direct Call é um recurso que adicionamos no Burst 1.5 e que permite que o código C# gerenciado chame diretamente um método compilado pelo Burst, sem passar pelo BurstCompiler.CompileFunctionPointer. Durante a recarga de um domínio, há algum trabalho de inicialização que precisa ser feito para conectar os métodos de chamada direta e, no Burst 1.7, tornamos essa inicialização até 33 vezes mais rápida.

Como última observação sobre o tópico do tempo de iteração, analisamos o custo da inicialização do SharedStatic. SharedStatic é um mecanismo que permite o compartilhamento de dados entre o C# gerenciado e o HPC#. No Burst 1.7, tornamos a inicialização do SharedStatic até 13 vezes mais rápida.

Os gráficos a seguir mostram as melhorias de desempenho no Burst 1.7, em comparação com o Burst 1.6. As medições foram feitas em um grande projeto de cliente. O primeiro gráfico abaixo mostra os tempos obtidos com um cronômetro (um cronômetro real, não System.Diagnostics.Stopwatch) observando o Editor, de modo que eles devem refletir o tipo de melhorias que você pode esperar ver no uso diário.

Melhorias no desempenho do Burst 1.7

O segundo gráfico abaixo se concentra apenas no Burst, portanto, exclui qualquer outra coisa que possa estar ocorrendo no Editor. Para esse projeto específico e arquivo modificado, o Burst 1.7 é mais rápido do que o Burst 1.6 em todos os três tempos:

  • Cache frio - o Burst ainda não armazenou em cache nenhum resultado de compilação para o código em seu projeto.
  • Cache quente - o Burst já compilou o código em seu projeto e precisa carregar os resultados da compilação em cache a partir do disco.
  • Alterar um arquivo - depois que um arquivo é alterado, o Burst verifica quais pontos de entrada precisam ser recompilados e os compila. Observe que a quantidade de melhoria no Burst 1.7 depende, em geral, de qual arquivo é alterado. Por exemplo, se você alterar um método que é usado por todos os pontos de entrada do Burst, a diferença entre o Burst 1.6 e o Burst 1.7 será menor. Neste exemplo, o próprio método do ponto de entrada foi alterado.
Melhorias no desempenho do Burst 1.7 2
Inspetor de explosão

O Burst Inspector (acessível em Jobs > Burst > Open Inspector...) é uma ferramenta incrivelmente útil para o trabalho de otimização. Com essa ferramenta, você pode visualizar o código de montagem que será executado na(s) CPU(s) de destino. No Burst 1.7, adicionamos vários recursos muito solicitados. Uma captura de tela vale mais que mil palavras, portanto, sem mais delongas:

Marcadores de ramo do inspetor de explosão

Como você pode ver, adicionamos marcadores de ramificação para facilitar a visualização dos caminhos de execução do código. Observe que os marcadores de ramificação podem ser desativados com a caixa de seleção "Show Branch Flow" para que não atrapalhem quando você não precisar deles. Um aspecto particularmente interessante desse recurso é que você pode clicar em uma seta de fluxo de ramificação e pular para a outra extremidade da seta, assim:

Exemplo de clique no marcador de ramificação para pular para o destino da ramificação

Blocos menos importantes de desmontagem (por exemplo, diretivas ou dados constantes) agora são recolhidos automaticamente, mas ainda podem ser alternados quando você quiser visualizá-los.

Outra novidade no Burst 1.7 é a capacidade de selecionar apenas uma seção da desmontagem e copiá-la.

Exemplo de seleção e cópia de uma seção específica de desmontagem

Melhorias diversas

Aqui está uma lista de melhorias menores, mas não menos importantes, no Burst 1.7.

  • As APIs Arm Neon vst1* agora são totalmente compatíveis. Adicionamos essas APIs no Burst 1.6, mas as protegemos por trás de um #define experimental. No Burst 1.7, eles não estão mais protegidos por essa #definição e são totalmente compatíveis.
  • System.Span<T> e System.ReadOnlySpan<T> agora são compatíveis com o código Bursted. Esses tipos não são permitidos como argumentos de ponto de entrada.
  • O Burst agora usa a versão 12.0.0 do LLVM por padrão, trazendo os mais recentes aprimoramentos de otimização do projeto LLVM.
  • Alteramos o pipeline de otimização do LLVM para executar o loop unroller exclusivamente após o vetorizador de loop. Isso melhora o codegen em muitos casos.
  • Fizemos com que o fmod e o módulo de ponto flutuante usassem um algoritmo mais rápido para melhorar o desempenho.
  • O Burst agora gera um link.xml automaticamente para evitar a remoção de IL, causando a falta de símbolos em tempo de execução devido ao uso de construtores estáticos.
  • Melhoramos o desempenho do compilador ao fazer grandes cópias de estruturas, detectando mais casos em que um load/store pode ser convertido com segurança em uma operação de movimentação de memória.
  • Fizemos uma alteração na forma como exibimos os tempos quando a opção "Show Timings" está ativada no menu Burst. Limpando e apresentando as informações de forma mais clara.
O que vem por aí para a Burst

Observe que o Burst 1.7 é a última versão compatível com o Unity 2019.4. A próxima versão do Burst terá como requisito mínimo o Unity 2020.3. Se tiver alguma opinião, dúvida ou apenas quiser nos informar o que está fazendo com o Burst, sinta-se à vontade para nos deixar uma mensagem no fórum do Burst.