Pular para o conteúdo principal
Os fabricantes de CPU estão constantemente equilibrando desempenho, consumo de energia e área do die. Isso acontece porque os clientes têm padrões de uso e prioridades diferentes. Uma pessoa que usa um computador desktop está mais interessada em desempenho, enquanto um usuário de laptop estará mais interessado na duração da bateria. Uma área de die menor pode significar custos de produção mais baixos. Para atender a esses requisitos concorrentes, os fabricantes de CPU projetam arquiteturas heterogêneas que permitem que o sistema se adapte dinamicamente às demandas atuais de carga de trabalho, mantendo a eficiência de custos. Os fabricantes de CPU implementaram uma topologia heterogênea usando núcleos de CPU com diferentes níveis de eficiência. Essa abordagem substituiu alguns núcleos de uma arquitetura de CPU existente por núcleos mais eficientes em termos de energia. Se o usuário não precisar do desempenho total da CPU, o sistema operacional desliga os núcleos de maior desempenho para economizar uma quantidade significativa de energia, resultando em maior duração da bateria. Quando é necessário mais desempenho, o sistema operacional pode ligar dinamicamente os núcleos de maior desempenho para lidar com o aumento da carga de trabalho.

Hardware

Diversos fornecedores independentes de hardware (IHVs) definem topologias de CPU heterogêneas de maneiras diferentes. A Intel e a Qualcomm usam os termos Performance e Efficiency, enquanto a AMD usa os termos Performance e Compact. Cada fornecedor faz concessões entre desempenho e eficiência ao projetar sua topologia de núcleos. Os exemplos a seguir ilustram algumas das escolhas de design envolvidas:
  • Tamanhos de cache diferentes
    • Os diferentes núcleos podem ter tamanhos de cache diferentes.
    • Por exemplo, os núcleos de desempenho podem ter caches L1 e L2 maiores.
  • Compartilhamento de cache
    • Pode haver diversos níveis de compartilhamento dos caches entre os núcleos.
    • Por exemplo, os núcleos de maior desempenho podem ter, cada um, um cache L2 privado, enquanto os núcleos mais eficientes podem compartilhar um único cache L2.
  • Suporte a multithreading simultâneo (SMT)
    • Alguns núcleos podem oferecer suporte a SMT, enquanto outros não.
    • A Intel chama o SMT de Hyper-Threading.
  • Layout interno do núcleo
    • Os recursos internos dos vários tipos de núcleo podem ser diferentes.
    • Por exemplo, os núcleos de desempenho podem incluir mais pipes de ponto flutuante, pipes de ALU ou faixas de dados mais largas.
  • Frequência máxima
    • A frequência máxima pode ser diferente entre os tipos de núcleo.
    • Por exemplo, os núcleos de desempenho podem atingir uma frequência mais alta do que os núcleos eficientes.
Essas mudanças foram projetadas para equilibrar desempenho e consumo de energia entre os núcleos de uma CPU. Um núcleo com frequência mais alta tem desempenho maior, ao custo de maior consumo de energia. Vários núcleos compartilhando o mesmo cache diminuem o tamanho do die, o que reduz o consumo de energia, porém ao custo de desempenho reduzido. O objetivo é permitir escolhas mais dinâmicas de desempenho e consumo de energia. Se o usuário não precisar do desempenho total, o sistema operacional alterna para núcleos mais eficientes para reduzir o consumo de energia. É importante observar que o Windows exige que todos os núcleos da CPU ofereçam suporte à mesma Arquitetura do Conjunto de Instruções (ISA). Esse requisito significa que, se uma CPU oferece suporte a um conjunto de instruções específico, todos os núcleos da CPU oferecem suporte a esse conjunto. Por exemplo, se a CPU informa que oferece suporte a AVX2, todos os núcleos oferecem suporte a AVX2. Para obter detalhes específicos sobre as diferenças entre núcleos de desempenho e eficientes, consulte a documentação oficial de cada IHV.

Números de desempenho

É esperado que núcleos com diferentes níveis de eficiência tenham desempenhos diferentes. Um núcleo é projetado para desempenho e o outro para economia de energia. A questão é o quanto os núcleos são diferentes. Os dados mostrados são um conjunto agregado de vários IHVs. Cada IHV tem uma escala diferente para cada teste, com base nas escolhas feitas para sua topologia. Embora os números exatos sejam diferentes, os padrões são semelhantes entre todos os IHVs. Além disso, cada geração de CPU faz concessões diferentes, o que ajusta seus números relativos. Gerar números para todos os IHVs e gerações existentes está além do escopo deste artigo.

Testes sintéticos

A matemática vetorial é uma parte importante do trabalho que um título de jogo realiza em um quadro. Essa carga de trabalho pode ser qualquer coisa, de física a IA e renderização. O jogo realiza esse trabalho usando tipos vetoriais com três ou quatro floats que cabem em um único registro SSE de 128 bits. Eles abrangem uma ampla variedade de operações, como produtos escalares, multiplicação de matrizes, cálculos de raiz quadrada e transformações de vetores. Diferenças de desempenho nessas operações podem ter um efeito significativo no tempo total do quadro. Os gráficos a seguir mostram o custo relativo de realizar sete operações matemáticas comuns. As medições usam um vetor de quatro valores de ponto flutuante de 32 bits armazenados em um único registro SSE de 128 bits. Uma matriz é composta por quatro vetores, totalizando dezesseis valores de ponto flutuante de 32 bits em quatro registros SSE de 128 bits. Essas operações foram selecionadas porque são usadas com frequência em um quadro.
  • Produto escalar: calcula o produto escalar de um vetor.
  • Transformação de vetor: transforma um vetor multiplicando-o por uma matriz.
  • Soma de vetores: soma dois vetores.
  • Produto vetorial: calcula o produto vetorial de dois vetores.
  • Seno vetorial: calcula uma aproximação do seno de cada elemento de um vetor.
  • FMA vetorial (multiplicação e adição fundidas): multiplica dois vetores e soma um terceiro.
  • Raiz quadrada inversa: calcula a raiz quadrada inversa do comprimento de um vetor.
Figura 1: Tempo gasto para realizar a operação. Quanto menor, melhor. Números de benchmark sintético heterogêneo Neste gráfico, o eixo y é o tempo gasto para realizar a operação. Cada barra representa o intervalo de tempo da operação medido em todos os IHVs: o tempo mínimo e máximo ao executar o teste em um núcleo de desempenho ou em um núcleo eficiente. Como esperado, o desempenho entre os tipos de núcleo é diferente. No entanto, a principal conclusão desses números é que o desempenho não escala de forma uniforme em todas as operações e IHVs. Embora a variabilidade dos resultados entre os IHVs tenha tendido a ser semelhante, alguns apresentaram variabilidade maior. As operações com maior variabilidade apareceram principalmente nas operações de Seno Vetorial e Raiz Quadrada Inversa. Essa diferença pode ser atribuída às escolhas de arquitetura entre núcleos de desempenho e eficientes. A causa exata dessa diferença pode vir de várias fontes. Por exemplo, os núcleos de maior desempenho podem ter mais pipes de ponto flutuante, o que permite mais operações em paralelo. O motivo exato é único para cada IHV e geração de CPU. Pode até haver uma configuração em que a diferença de desempenho não exista para determinadas operações. No fim, um título precisa levar em conta essa variabilidade entre os IHVs.

Mundo real

Os números anteriores mostram benchmarks específicos de forma isolada e contam apenas parte da história. Os números a seguir vêm de benchmarks de um mecanismo de jogo AAA que usa dois threads principais (Simulação e Renderização) com um conjunto de threads de trabalho. O benchmark usa três configurações de teste.
  • Os dois threads principais são executados apenas nos núcleos de maior desempenho.
  • Os dois threads principais são executados apenas nos núcleos eficientes.
  • Os dois threads principais são executados em todos os núcleos do sistema.
Em cada configuração de teste, os threads de trabalho podem flutuar livremente entre todos os núcleos do sistema. O trabalho de renderização usa a menor resolução e qualidade possíveis. Essa configuração garante que o título fique limitado pela CPU durante toda a execução do teste. Ela também faz com que o thread de Simulação seja o fator determinante da taxa de quadros. Este gráfico mostra o tempo gasto em cada thread durante um quadro. Ele mostra tanto o tempo médio de quadro quanto o 1% mais alto. O 1% mais alto é o limite para o 1% dos quadros mais longos. Apenas 1% de todos os quadros fica acima desse valor. Esse número dá uma boa noção da quantidade de quadros com travamentos. Quanto mais distante da média, pior é o travamento do título. Em todos os casos, valores mais baixos indicam menos quadros longos e menos travamentos visíveis. Como mencionado anteriormente, os dados mostrados são um conjunto agregado de vários IHVs. Cada IHV tem uma escala diferente para cada teste, com base nas escolhas feitas para sua topologia. Embora os números exatos sejam diferentes, os padrões são semelhantes entre os IHVs. Cada geração de CPU pode fazer concessões diferentes, o que ajusta seus números relativos. Gerar números para todos os IHVs e gerações de CPU existentes está além do escopo deste documento. Figura 2: Tempo médio gasto e 1% mais alto. Quanto menor, melhor. Números de benchmark heterogêneo do mundo real Neste gráfico, o eixo y é o tempo gasto para um quadro. Cada barra representa o intervalo de tempo da operação medido em todos os IHVs: o tempo mínimo e máximo para cada topologia de threads testada. O agendador de threads do sistema operacional usa heurísticas para determinar a quantidade de trabalho realizada por um thread. Essas heurísticas são uma combinação de escolhas do sistema operacional e ajustes de driver feitos por um IHV. O agendador usa essas informações para escolher em quais núcleos um determinado thread deve ser executado. Quando decide que um thread está realizando uma grande quantidade de trabalho, o agendador move esse thread para um núcleo de maior desempenho. Por causa das heurísticas do agendador, pode ocorrer um comportamento contraintuitivo em que o título é executado mais rapidamente quando os threads críticos podem flutuar livremente. Esse comportamento nem sempre acontece e depende da carga de trabalho, da topologia dos núcleos e das heurísticas exatas do agendador. No caso testado aqui, o thread de Simulação passa mais tempo em execução em cada quadro do que o thread de Renderização. O agendador prefere colocar esse thread em um núcleo de maior desempenho. Ele também decide colocar o thread de Renderização em um núcleo de menor desempenho, já que esse thread passa mais tempo suspenso aguardando trabalho. O efeito final é que essa decisão libera um núcleo de maior desempenho para um dos threads de trabalho. Se o thread de Renderização estivesse realizando mais trabalho, essa situação poderia não ocorrer. No entanto, a conclusão mais interessante deste gráfico está no número do 1% mais alto. Mesmo que a média seja a mesma quando os threads críticos flutuam livremente, o 1% mais alto é pior do que quando os threads críticos estão fixados nos núcleos de desempenho. Essa condição significa que a taxa de quadros apresenta mais travamentos quando os threads críticos flutuam livremente. O motivo mais comum é que as heurísticas do agendador operam sobre uma janela deslizante. Leva tempo para responder a um pico no trabalho necessário para um quadro. Durante esse tempo, um thread crítico pode estar sendo executado em um núcleo de menor desempenho.
Cada fabricante pode ajustar essas heurísticas do agendador para adaptá-las ao seu hardware. Por exemplo, a AMD tem o Workload Profile Scheduling e a Intel tem a tecnologia Thread Director. Cada IHV também costuma ajustar as heurísticas para corresponder à topologia específica do SoC.

Recomendações

Afinidade de threads

A recomendação de afinidade de threads ao executar em um computador desktop com apenas uma classe de eficiência é evitar definir afinidades rígidas de threads e, em vez disso, permitir que os threads flutuem entre todos os núcleos. O principal motivo dessa incerteza é que não se sabe com antecedência quais outros processos podem estar em execução no computador do usuário. É possível que um thread com afinidade rígida acabe compartilhando um núcleo com outro thread de alta prioridade do sistema. O efeito final é que o thread do título fica sem tempo de execução. Se essa contenção ocorrer em um thread crítico para o quadro, o título pode apresentar tempos de quadro inconsistentes. Você deve garantir que o sistema operacional tenha para onde mover os threads do título para mantê-los em execução. No entanto, essa recomendação precisa mudar ao executar em CPUs heterogêneas. O principal motivo é que o sistema operacional não sabe necessariamente quais threads ou trabalhos do título são críticos para o quadro. Ele tem algumas heurísticas para determinar o que considera threads críticos para o quadro, mas essas heurísticas ainda podem fazer escolhas incorretas. Ele pode decidir mover um desses threads ou trabalhos para um núcleo de menor desempenho e, assim, aumentar a probabilidade de problemas de desempenho no título. A recomendação é permitir que os threads do título sejam executados em, no mínimo, três a quatro núcleos, sendo preferível mais. Por exemplo, em um sistema de nível inferior que tenha um núcleo de maior desempenho e três núcleos de menor desempenho, você deve permitir que os threads flutuem entre todos os núcleos. Em computadores com três ou mais núcleos de desempenho, você pode restringir os threads críticos para o quadro apenas a esses núcleos de maior desempenho. Em computadores de nível superior com muitos núcleos que também oferecem suporte a SMT, alguns títulos podem tentar fixar seus threads em núcleos físicos. Essa técnica evita a contenção no nível do núcleo físico, já que vários threads de alta prioridade compartilham os mesmos recursos de um núcleo físico. Em geral, porém, não é recomendável considerar esse caso. O sistema operacional já aplica esse comportamento em todo o sistema. Ele agenda os threads primeiro entre os núcleos físicos e usa mais núcleos lógicos somente quando necessário. O único caso que um título deve considerar é quando há núcleos de maior desempenho suficientes no sistema para dar suporte aos threads críticos do título. Nesse caso, pode ser desejável fixar os threads críticos para o quadro em núcleos de maior desempenho. No entanto, esses threads devem poder flutuar entre todos os núcleos de maior desempenho. Embora, em alguns casos, permitir que todos os threads flutuem entre todos os núcleos possa melhorar o desempenho, esse comportamento não é consistente entre todos os fabricantes de CPU. Se o título implementar um sistema de roubo de trabalho capaz de equilibrar totalmente a carga de trabalho entre todos os threads, qualquer thread de trabalho deverá poder flutuar entre todos os núcleos. Não importa se são threads de trabalho de alta ou baixa prioridade. O algoritmo de roubo de trabalho equilibra a carga automaticamente e permite que a maior quantidade de trabalho seja concluída no menor tempo. Threads nos núcleos de maior desempenho executam mais trabalhos durante o quadro. Se houver vários threads críticos para o quadro, pode ser útil definir sua afinidade de modo que dois threads críticos nunca possam ser executados no mesmo núcleo. Por exemplo, se houver dois threads críticos para o quadro, definir suas afinidades como mutuamente exclusivas (OU exclusivo) elimina a possibilidade de o sistema operacional fazer com que os threads disputem entre si. Novamente, porém, considere essa opção apenas se houver núcleos suficientes para dar suporte a esse caso e, ao mesmo tempo, permitir que cada thread crítico para o quadro flutue entre, no mínimo, três a quatro núcleos.

Topologia de threads

Ao considerar como atribuir trabalho a threads em um ambiente heterogêneo, os dados principais giram em torno da duração das várias tarefas e de como elas interagem entre si. Qual é a duração média de cada tarefa, quais são as dependências entre as tarefas, quais são as prioridades de cada tarefa etc. Quanto os threads de trabalho conseguem absorver picos de tempo em quaisquer threads ou trabalhos críticos? Se um desses threads ou trabalhos for executado 35% mais lentamente, quanto isso afeta o tempo de quadro? Por exemplo, se uma tarefa demorar mais, quanto esse atraso afeta o restante do quadro? O sistema fica parado até que essa tarefa seja concluída? Pode ser útil determinar quanto um sistema heterogêneo afeta o tempo de quadro adicionando sobrecarga extra aos threads ou trabalhos críticos. Como teste, faça com que um trabalho ou bloco de trabalho leve aleatoriamente de 25% a 35% a mais de tempo. O grau de mudança no tempo total do quadro indica o quanto o sistema de trabalhos consegue absorver picos de execução. A situação ideal é que os tempos de quadro quase não mudem. Isso significa que o sistema consegue absorver picos arbitrários no tempo de quadro. Os picos vêm da execução em um núcleo de menor desempenho ou de outro processo aleatório do sistema usando tempo de CPU.

Comunicação entre threads

É preciso ter cuidado com a comunicação entre threads usando primitivas de bloqueio. A sobrecarga de uma troca de contexto está fortemente ligada ao C-State do núcleo receptor antes de o novo thread começar a ser executado. O núcleo precisa estar em C0, o estado de execução, antes que o novo thread possa começar a ser executado. O cenário mais barato é quando o núcleo já estava em execução, ou seja, já está em C0. No entanto, se o núcleo estiver ocioso, ele estará em um C-State inferior. O nível do C-State corresponde a níveis mais profundos de suspensão. Uma suspensão mais profunda resulta em menos energia usada pelo núcleo. No entanto, é mais caro despertar e voltar a executar a partir de uma suspensão mais profunda. O C-State de baixo consumo mais comum é o C1, que pode adicionar uma sobrecarga de 2 a 7 μs. O C-State seguinte, C2, pode adicionar uma sobrecarga de aproximadamente 40 a 100 μs. O número exato é específico do IHV e do SoC. Há muitas variáveis que controlam em qual C-State um núcleo fica quando ocioso; trata-se de um equilíbrio entre capacidade de resposta e consumo de energia. Um C-State mais baixo usa menos energia do que um C-State mais alto. É comum que um núcleo entre primeiro em C1 e depois mude para C2 se não tiver executado código por algum tempo. Há outra preocupação: o que acontece quando o thread que envia o trabalho e o thread que executa o trabalho estão em núcleos com perfis de desempenho diferentes. Tecnicamente, é possível que o thread de trabalho conclua trabalhos mais rapidamente do que novos trabalhos são criados. Essa situação é mais provável quando o thread que executa o trabalho está em um núcleo mais rápido do que o thread que envia os trabalhos. Se um trabalho levar menos tempo para ser executado do que para ser criado, o título pode entrar em uma situação em que um thread de trabalho fica constantemente suspenso aguardando novos trabalhos. O efeito final é que os trabalhos se tornam mais caros de executar, pois o thread de trabalho é suspenso constantemente. O custo da sobrecarga de uma troca de contexto é adicionado ao tempo de execução de cada trabalho. Paradoxalmente, essa sobrecarga pode levar a taxas de quadros mais baixas ao executar em núcleos de maior desempenho. Por exemplo, um trabalho que levava 250 μs pode de repente começar a levar 275 μs; essa regressão é uma queda de 10% no desempenho. Por causa desse caso, a recomendação é que os trabalhos sejam enviados em lotes, e não à medida que são criados. Por exemplo, se o sistema seguir um padrão em que cria um trabalho, envia o trabalho, cria um trabalho, envia um trabalho etc., esse padrão deve ser ajustado para primeiro criar um lote de trabalhos e depois enviar todos ao mesmo tempo. Se o título estiver usando um objeto que exige WaitForSingleObject, ele deverá ser colocado dentro de um pequeno loop de rotação (spin). Chame a função com um tempo limite de 0 e, quando a rotação terminar, use o valor de tempo limite normal do título. A melhor solução para esse problema, no entanto, é usar APIs de sincronização modernas, como Bloqueios SRW (Slim Reader/Writer), Seções Críticas e WaitOnAddress. Todas essas APIs de sincronização incluem internamente alguma forma de rotação, o que pode impedir que um thread seja suspenso constantemente. Essa rotação é especialmente útil para bloqueios mantidos por um curto período. É importante evitar spin locks longos. Por exemplo, um padrão em que os threads ficam constantemente em rotação aguardando trabalho a ser realizado. Se houver outro trabalho a ser realizado no núcleo, o agendador acabará suspendendo o thread em rotação para realizar esse trabalho. Quando essa preempção ocorre, há uma grande probabilidade de que o thread suspenso permaneça suspenso por um período significativo. Todo esse comportamento existe para evitar a falta de recursos para outros threads. Como o título tem pouco controle sobre quando a suspensão acontece, isso pode levar a travamentos na taxa de quadros.

Sistemas de trabalhos

Para obter o melhor desempenho, estruture o mecanismo em torno de trabalhos, em vez de depender de threads dedicados, de longa duração e críticos para o quadro. Por exemplo, um modelo de threads de Simulação/Renderização cria dois threads persistentes críticos para o quadro. No entanto, trabalhos longos podem fazer com que qualquer thread de trabalho se comporte como um thread crítico para o quadro. Se um trabalho levar 10 ms, o thread que o executa se tornará crítico para o quadro durante esse período, independentemente de sua função original.

Roubo de trabalho

A principal recomendação é usar o roubo de trabalho em todo o sistema de trabalhos e permitir que todos os threads críticos para o quadro participem do algoritmo de roubo de trabalho. Por exemplo, se o thread de renderização estiver aguardando a conclusão de trabalhos relacionados à renderização, ele deverá executar alguns desses trabalhos. Esse comportamento já é uma prática comum em muitos mecanismos de jogo. No entanto, vale a pena mencioná-lo aqui porque esse tipo de comportamento é fundamental para que o mecanismo de jogo consiga absorver picos de quadro causados por núcleos heterogêneos e por uma possível preempção do sistema operacional. Quando um trabalho leva mais tempo para ser executado, aumenta o risco de um pico no tempo de quadro. Esse comportamento pode ser causado pela execução do trabalho em um núcleo de menor desempenho ou por outra atividade no PC. A recomendação é que o mecanismo tenha como objetivo que um trabalho leve cerca de dois por cento do quadro. Esse orçamento significa, por exemplo, no máximo cerca de 333 μs para um jogo executado a 60 fps. Se necessário, vários trabalhos menores devem ser agrupados em um trabalho maior para atingir os dois por cento. Essa abordagem oferece um bom equilíbrio entre o tamanho do trabalho, a comunicação entre threads e a capacidade de absorver picos. Estes exemplos mostram os efeitos que trabalhos longos e críticos para o quadro podem ter no desempenho do sistema. Nestes exemplos, cada trabalho consiste no mesmo número de operações. Neste exemplo, há um único trabalho que leva 375 μs em um núcleo lento e 250 μs em um núcleo rápido. O trabalho mais longo (long pole) é 6 vezes mais caro do que os outros trabalhos. A pior situação ocorre quando o trabalho mais longo acaba em um dos núcleos lentos. Isso pode ter um efeito drástico nos tempos de quadro. Nesse cenário, o tempo total para executar o trabalho é de 2.250 μs, seis vezes 375 μs. Figura 3: Exemplo de trabalho mais longo executado em um núcleo mais lento. Exemplo de trabalho mais longo com roubo de trabalho heterogêneo em um núcleo mais lento A situação melhora quando o trabalho mais longo acaba em um núcleo mais rápido. Nesse caso, o tempo total é de 1.500 μs. Ainda não é ótimo, mas é melhor. Figura 4: Exemplo de trabalho mais longo executado em um núcleo mais rápido. Exemplo de trabalho mais longo com roubo de trabalho heterogêneo em um núcleo mais rápido O melhor resultado evita trabalhos longos mantendo os tamanhos dos trabalhos pequenos e distribuídos uniformemente. Neste exemplo, o tempo total de execução cai para 1.125 μs, que é metade do tempo do exemplo anterior, com a mesma quantidade de trabalho concluída. Figura 5: Evite trabalhos longos usando durações de trabalho adequadas. Roubo de trabalho heterogêneo com duração de trabalho adequada Mais importante ainda, se o sistema operacional tentar interromper no meio da execução de um trabalho, o sistema equilibra automaticamente a carga de trabalho. Nesse caso, o sistema operacional interrompeu o título com uma tarefa de 375 μs em um núcleo rápido. Esse reequilíbrio não tem efeito no tempo total do quadro, que permanece em 1.125 μs. Um dos trabalhos migrou para o tempo livre em um núcleo lento. Figura 6: A interrupção do sistema operacional com reequilíbrio da carga de trabalho mantém o tempo de quadro estável. Roubo de trabalho heterogêneo com duração de trabalho adequada e interrupção Estes exemplos abrangem apenas o caso em que o trabalho mais longo pode começar imediatamente; se ele só puder começar mais tarde na fila de trabalhos, a situação piora. Tudo volta à Lei de Amdahl, segundo a qual o tempo de execução de qualquer sistema está vinculado à parte de execução mais longa desse sistema. É impossível para o mecanismo absorver picos que aumentem o tempo de execução desses threads mais longos. Esses picos podem vir da execução em um núcleo mais lento ou de interrupções de outros processos de alta prioridade do sistema.

Conclusão

Ao implementar essas recomendações, você garante que o jogo tenha um desempenho confiável e permaneça resiliente em diferentes arquiteturas de CPU e diante de interferências de outros processos do Windows.

Apêndice

Determinar a classe de eficiência dos núcleos

Use a função GetLogicalProcessorInformationEx para determinar a classe de eficiência de cada processador do sistema. Itere pelos dados retornados pela função procurando um bloco RelationProcessorCore que contenha a classe de eficiência e a máscara do núcleo.

Fixar threads com base no consumo de energia

Como mencionado, a fixação de núcleos usando afinidade não é recomendada no ambiente desktop devido à possível interferência de outros processos no computador. No entanto, o Windows oferece maneiras de um título dar dicas ao sistema operacional para recomendar onde o trabalho deve ser executado. Uma forma de fornecer essa orientação é por meio das APIs de gerenciamento de energia.

Usar CPU Sets para consultar a classe de eficiência

Usar CPU Sets é outro método para consultar a classe de eficiência de cada núcleo do sistema.

Usar CPU Sets para atribuir threads a classes de eficiência

CPU Sets também podem ser usados no lugar da definição explícita da máscara de afinidade de um thread. A recomendação é usar CPU Sets em vez de máscaras de afinidade explícitas.
Última modificação em 6 de outubro de 2026