Este é um assunto complicado, dependendo de várias variáveis, incluindo qual agendador, driver e governador de frequência da CPU, latências de estado ocioso, processador ...
E, embora muito trabalho tenha sido feito para fazer com que os vários drivers de escala de frequência da CPU respondam adequadamente às cargas de trabalho, há simplesmente cenários em que os resultados são surpreendentemente baixos. Isso pode ocorrer com aplicativos multi threaded ou single threaded. Por exemplo, o ffmpeg e a maneira estranha como ele gira através de CPUs, é um aplicativo particularmente desafiador para os drivers de escala de frequência da CPU. No meu computador com 8 CPUs, obtenho melhores resultados com o teste phoronix ffmpeg se o limitar a 4 CPUs em vez de 8.
Vamos trabalhar com um simples exemplo de thread único. Eu tenho um programa de gravação de CPU simples que vai fazer um pequeno pedaço de trabalho, e quando feito um script de nível mais alto irá girar para fora outros processos que fazem outro pequeno pedaço de trabalho, e assim por diante para alguns loops. Se eu executar este trabalho sem restringir o número de CPUs alocadas, ele levará 104 segundos, mas se eu restringi-lo a uma CPU, ele levará 54 segundos. Por que uma diferença tão intuitiva e drástica? Como durante uma parte do trabalho, a combinação de driver / regulador de escala de frequência da CPU percebe que a CPU está totalmente carregada e começou a aumentar a frequência da CPU. No entanto, enquanto isso, o pedaço de trabalho termina e o próximo é lançado. Agora, o programador ainda não sabe que o primeiro bloco de trabalho terminou, por isso acha que a CPU está totalmente carregada e, portanto, decide atribuir outra CPU ao novo bloco de trabalho. A primeira CPU entra em um estado ocioso e não influencia mais a freqüência de operação desejada da CPU. Enquanto isso, o novo processador só começa a aumentar sua frequência de operação em resposta à carga. Esse ciclo continua e continua com o resultado de que a freqüência de operação da CPU nunca fica muito alta.
Agora, no caso em que apenas uma CPU é alocada para a tarefa, nunca há uma lacuna de carga nessa CPU e, por fim, ela atinge a frequência máxima de operação e os blocos de trabalho são concluídos muito mais rapidamente.
Exemplo de dados (sempre o mesmo trabalho, nenhum pedido de E / S envolvido):
One CPU allocated:
(driver = intel_pstate; governor = powersave):
real 0m54.830s
user 0m48.112s
sys 0m0.272s
No restriction on CPU allocation (i.e. all 8 are available):
(driver = intel_pstate; governor = powersave):
real 1m54.938s
user 1m47.948s
sys 0m0.336s
No restriction on CPU allocation (i.e. all 8 are available):
(driver = intel_pstate; governor = performance):
real 0m52.851s
user 0m48.044s
sys 0m0.212s
Então, por que não usar o governador de desempenho o tempo todo? Porque, em geral, isso desperdiçaria muita energia desnecessariamente. São apenas esses casos especiais de uso, onde pode ser melhor simplesmente usar o governador de desempenho.