Analisar a programação de linhas de execução

Há algumas coisas a considerar para determinar se as linhas de execução do processo do jogo estão sendo usadas e programadas adequadamente para o melhor desempenho.

  • Frame Pacing
  • Multithreading e paralelização de linhas de execução
  • Afinidade do núcleo da CPU

Usar várias linhas de execução

Muitos jogos e mecanismos de jogos usam multithreading para dividir o trabalho da CPU em tarefas lógicas, que podem ser executadas de forma independente. Uma configuração típica é uma linha de execução de jogo para entrada e lógica de jogo, uma linha de execução de renderização para preparar e enviar objetos a serem desenhados e linhas de execução de worker para outras subtarefas, como animações ou áudio.

Recomendamos paralelizar as linhas de execução para aproveitar os ganhos de desempenho da multithreading. Um exemplo disso é um cenário em que as linhas de execução do jogo e de renderização estão sendo executadas parcial ou totalmente de maneira simultânea em núcleos diferentes. Isso nem sempre é possível, como em casos com dependências de dados compartilhados. No entanto, quando possível, isso pode resultar em tempos de CPU mais baixos e, portanto, taxas de frames potencialmente mais altas.

Jogo com uma linha de execução principal e de renderização bem paralelizadas, além de uma linha de execução de worker e de áudio.
Figura 1. Jogo com uma linha de execução principal e de renderização bem paralelizadas, além de uma linha de execução de worker e de áudio

Afinidade do núcleo da CPU

Um fator que afeta significativamente o desempenho das cargas de trabalho da CPU é como elas são programadas nos núcleos. Isso pode ser dividido em dois componentes:

  • Se as linhas de execução do jogo estão sendo executadas no núcleo mais adequado para a carga de trabalho.
  • Se as linhas de execução do jogo mudam de núcleos com frequência.

Os dispositivos modernos costumam usar uma arquitetura chamada computação heterogênea, em que os núcleos têm diferentes níveis de desempenho:

  • Um ou alguns núcleos oferecem o melhor desempenho máximo, mas consomem mais energia. Às vezes, eles são chamados de núcleos "grandes".
  • Outros núcleos têm desempenho máximo menor, mas são mais eficientes em termos de energia. Às vezes, eles são chamados de núcleos "pequenos".
  • Opcional: um ou mais núcleos oferecem um equilíbrio entre desempenho e energia. Às vezes, elas são chamadas de cores "intermediárias".

É possível investigar o comportamento da linha de execução da CPU em Uso da CPU ativando a CPU na configuração do perfil ao fazer um rastreamento. Ao ampliar uma seção do rastreamento <200 ms, você pode ver os processos individuais em execução nos núcleos da CPU do dispositivo. Normalmente, núcleos menores correspondem a índices menores (por exemplo, CPUs "0"-"3"), enquanto núcleos maiores correspondem a índices mais altos (por exemplo, CPUs "6"-"7"). Se houver núcleos intermediários, eles vão ocupar índices entre os dois (por exemplo, CPUs "5"-"6"). Isso é uma convenção comum, mas não é uma garantia.

Se você descobrir que determinadas linhas de execução estão sendo programadas em CPUs que não atendem às necessidades de desempenho ou energia, defina manualmente a afinidade de CPU para essas linhas de execução.

Jogo com linha de execução principal e de renderização sendo executadas principalmente nos núcleos grandes (CPU 6-7), mostrado em azul claro
Figura 2. Jogo com a linha de execução principal e de renderização sendo executada principalmente nos núcleos grandes (CPU 6-7), mostrada em azul claro

Você também pode observar se as linhas de execução alternam entre núcleos. Essas trocas de núcleo geram alguma sobrecarga devido à troca de contexto e à perda de estado com o cache/registros de um núcleo.

Jogo com linha de execução principal (Thread-7) e de renderização (Thread-8) que alternam entre núcleos, mostrado em roxo
Figura 3. Jogo com linha de execução principal (Thread-7) e de renderização (Thread-8) que alternam entre núcleos, mostrado em roxo

Definir a afinidade da CPU para uma linha de execução instrui o sistema a programá-la no núcleo especificado quando o jogo está em primeiro plano. Há vários fatores a serem considerados ao fazer isso:

  • O software da plataforma não pode ajustar dinamicamente o posicionamento de tarefas para fatores de tempo de execução, como carga e limitação térmica.
  • Os testes de desempenho em dispositivos diferentes podem gerar características de desempenho muito diferentes, especialmente se os dispositivos variarem consideravelmente por faixa de preço ou data de lançamento.

    Um dispositivo mais novo ou mais caro pode executar uma determinada carga de trabalho confortavelmente em um núcleo pequeno, mas um dispositivo mais antigo ou mais acessível pode exigir um núcleo maior para cumprir os prazos dessa mesma carga de trabalho.

  • Ao forçar afinidades com núcleos grandes, você pode aumentar desnecessariamente o consumo de bateria e a carga térmica.

Por esses motivos, geralmente é melhor evitar definir afinidades de CPU manualmente.