Por que um programa exigiria um número mínimo específico de núcleos de CPU?


55

É possível escrever código (ou software completo, em vez de um pedaço de código) que não funcionará corretamente quando executado em uma CPU com menos de N número de núcleos? Sem verificar explicitamente e falhar de propósito:

SE (noOfCores <4) ENTÃO não é executado corretamente de propósito

Estou observando os requisitos mínimos de sistema de um jogo ( Dragon Age: Inquisition ), e ele declara um mínimo de uma CPU de quatro núcleos. Muitos jogadores dizem que ele NÃO roda em CPUs de dois núcleos e até no Intel Core i3s com dois núcleos físicos e dois lógicos. E NÃO é um problema de poder de computação.

Pelo meu entendimento, os threads são completamente isolados da CPU pelo SO, pois isso não pode ser feito.

Apenas para esclarecer as coisas:

NÃO estou perguntando "Posso descobrir o número de núcleos da CPU no código e falhar de propósito?" ... Esse código seria mal intencionado (obriga a comprar uma CPU mais cara para executar um programa - sem a necessidade de energia computacional). Estou pedindo que seu código, digamos, tenha quatro threads e falhe quando dois threads são executados no mesmo núcleo físico (sem verificar explicitamente as informações do sistema e falhar propositadamente) .

Em resumo, pode haver software que exija vários núcleos, sem a necessidade de poder de computação adicional proveniente de vários núcleos? Exigiria apenas N núcleos físicos separados.


11
Se você ler minha pergunta com atenção, verá que eles não estão fazendo a mesma coisa.
Ullmz

21
Como o número de núcleos pode ser recuperado, ele pode ser comparado a N e, se essa comparação for avaliada como verdadeira, o código poderá fazer o que quiser, incluindo, entre outros, o comportamento de maneiras não anunciadas. Qual a sua pergunta?

3
Você tem certeza de que o problema está realmente e diretamente relacionado ao número de núcleos? Talvez o jogo mencionado seja parcialmente baseado apenas em um recurso (corretamente) fornecido pela CPU com pelo menos 4 núcleos?
precisa saber é o seguinte

25
Observe que "requisitos mínimos do sistema" geralmente são "requisitos mínimos do sistema para executar com desempenho aceitável", especialmente em jogos. É muito possível que Dragon Age pudesse, em teoria, rodar em uma única caixa de núcleo, mas se você o fizesse, isso mostraria quedas de quadros maciças. Portanto, eles exigem esse número de núcleos para não forçar você a comprar hardware, mas evitar reclamações de qualidade dos usuários de hardware de ponta.
Gort the Robot

3
@Sebb: Eu acho que você gosta de algo: se 4 núcleos físicos se correlacionam com mais cache, em seguida, 2 físicos / 4 lógicos, então o jogo pode estar naturalmente sufocando em máquinas 2x2 sem atingir seus limites de poder de processamento, porque está faltando no cache todos os Tempo. O teste seria encontrar uma CPU com 2x2 núcleos e cargas de cache, ou 4 núcleos e pouco cache, e ver o que acontece.
9608 Steve JobsMay

Respostas:


45

Pode ser possível fazer isso "por acidente" com o uso descuidado da afinidade central. Considere o seguinte pseudocódigo:

  • iniciar um tópico
  • nesse segmento, descubra em que núcleo ele está sendo executado
  • definir sua afinidade de CPU para esse núcleo
  • comece a fazer algo computacionalmente intensivo / loop para sempre

Se você iniciar quatro deles em uma CPU de dois núcleos, algo ocorrerá errado com a configuração de afinidade de núcleo ou você terminará com dois threads sobrecarregando os núcleos disponíveis e dois threads que nunca são agendados. Em nenhum momento ele perguntou explicitamente quantos núcleos existem no total.

(Se você possui threads de longa execução, definir a afinidade da CPU geralmente melhora a taxa de transferência)

A idéia de que as empresas de jogos estão "forçando" as pessoas a comprar hardware mais caro sem uma boa razão não é muito plausível. Só pode perder clientes para eles.

Edit: este post agora tem 33 votos positivos, o que é bastante dado que se baseia em suposições educadas!

Parece que as pessoas têm DA: I para executar mal em sistemas de núcleo duplo: http://www.dsogaming.com/pc-performance-analyses/dragon-age-inquisition-pc-performance-analysis/ Essa análise menciona que a situação melhora muito se o hyperthreading estiver ativado. Dado que o HT não adiciona mais unidades ou cache de problema de instrução, ele apenas permite que um thread seja executado enquanto outro está em um travamento de cache, o que sugere fortemente que ele está vinculado apenas ao número de threads.

Outro pôster afirma que a alteração dos drivers gráficos funciona: http://answers.ea.com/t5/Dragon-Age-Inquisition/Working-solution-for-Intel-dual-core-CPUs/td-p/3994141 ; dado que os drivers gráficos tendem a ser uma colméia miserável de escória e vilania, isso não é surpreendente. Um conjunto notório de drivers tinha um modo "correto e lento" versus "rápido e incorreto" que foi selecionado se chamado no QUAKE.EXE. É perfeitamente possível que os drivers se comportem de maneira diferente para diferentes números de CPUs aparentes. Talvez (voltando à especulação) um mecanismo de sincronização diferente seja usado. Uso indevido de spinlocks ?

"O uso indevido de primitivas de bloqueio e sincronização" é uma fonte muito, muito comum de erros. (O bug que eu deveria estar olhando no trabalho enquanto escrevia isso é "falha se alterar as configurações da impressora ao mesmo tempo em que o trabalho de impressão termina").

Editar 2: os comentários mencionam o sistema operacional tentando evitar a inanição do encadeamento. Observe que o jogo pode ter seu próprio quase agendador interno para atribuir trabalho a threads, e haverá um mecanismo semelhante na própria placa de vídeo (que é efetivamente um sistema de multitarefa próprio). As chances de um bug em um desses ou a interação entre eles são bastante altas.

www.ecsl.cs.sunysb.edu/tr/ashok.pdf (2008) é uma tese de pós-graduação sobre melhor programação para placas gráficas que menciona explicitamente que elas normalmente usam programação de primeiro a chegar, primeiro a ser servido, fácil de implementar em sistemas não-preventivos. A situação melhorou? Provavelmente não.


11
Sim, existem duas partes para responder a essa pergunta: a afinidade da CPU permite codificar algo que tornaria isso um requisito técnico no Windows; a resposta alternativa é que os sistemas em tempo real podem definitivamente exigir essas coisas. +1 por ser a única pessoa a mencionar a afinidade da CPU, que é realmente o culpado mais provável pelo que está sendo solicitado aqui.
Jimmy Hoffa

3
O que pode dar errado se você definir a afinidade para o núcleo atual? Com multitarefa preemptiva, o segmento em espera será agendado, a menos que o atual tenha a máxima prioridade possível ("tempo real" no Windows). Eu veria outro cenário: a cada um dos quatro threads é atribuída uma afinidade definida estaticamente de 1,2,4,8; nesse caso, os dois últimos threads nunca serão agendados (embora eu não tenha certeza se a afinidade está configurada como efetiva). zero vai ter sucesso).
Ruslan

@Ruslan Talvez a tentativa de definir afinidade inválida possa travar o aplicativo em primeiro lugar?
Luaan 8/01/15

11
@ Huaan bem, isso não é uma operação arriscada que pode levar a um acidente. O máximo que eu esperaria é um erro retornado pelo sistema operacional. Acabei de verificar, no Linux, recebo o erro "Argumento inválido". Não sei o que o Windows diria.
Ruslan

@Ruslan Todo sistema operacional importante há certamente mais de uma década inclui código para evitar a inanição de threads (geralmente aumentando a prioridade de um thread depois que ele não é executado por tempo suficiente).
Voo

34

Pode ser necessário ter 4 núcleos porque o aplicativo executa quatro tarefas em threads paralelos e espera que eles terminem quase simultaneamente.

Quando cada encadeamento é executado por um núcleo separado e todos os encadeamentos possuem exatamente a mesma carga de trabalho computacional, é bem provável que (mas longe de ser garantido) termine aproximadamente ao mesmo tempo. Mas quando dois threads são executados em um núcleo, o tempo será muito menos previsível, pois o núcleo alternará o contexto entre os dois segmentos o tempo todo.

Os erros que ocorrem devido ao tempo inesperado do encadeamento são chamados de " condições de corrida ".

No contexto do desenvolvimento do jogo, uma arquitetura plausível com esse tipo de problema pode ser aquela em que diferentes recursos do jogo são simulados em tempo real por diferentes threads da CPU. Quando cada recurso é executado em um próprio núcleo, todos são simulados com aproximadamente a mesma velocidade. Mas quando dois recursos rodam em um núcleo, ambos são simulados apenas com a metade da velocidade do resto do mundo do jogo, o que pode causar todo tipo de comportamento estranho.

Observe que uma arquitetura de software que depende de threads independentes executados com horários específicos é extremamente frágil e é um sinal de péssimo entendimento da programação simultânea. Existem recursos disponíveis em praticamente todas as APIs de multithreading para sincronizar threads explicitamente para evitar esses tipos de problemas.


11
Mas qualquer jogo tem uma dependência frágil de poder concluir todo o cálculo para o próximo quadro a tempo de renderizá-lo com uma frequência razoável. Mesmo que seus 4 threads estejam sincronizados corretamente, pode ser impossível renderizar em tempo hábil, e não há benefício em um jogo que seja computacionalmente correto, mas não jogável devido a atraso e interrupção.
inútil

11
@ Useless: Isso não é verdade. Você pode, por exemplo, quadros de buffer ou dados de simulação para ocultar qualquer interrupção, e há projetos simultâneos que são mais consistentes. Concluir todo o processamento em X tempo e exigir a sincronização exata desse processamento são questões diferentes.
DeadMG

23
"uma arquitetura de software que depende de threads independentes executados com horários específicos é extremamente frágil". É exatamente por isso que não consigo imaginar um jogo que não seja executado com 2 núcleos, mas que trabalhe com 4 núcleos de maneira confiável. Mesmo com 4 núcleos, o tempo será imprevisível; portanto, a condição de corrida também ocorreria, mesmo que com menos frequência.
Svick

8
@ Rick, é claro. Mas a pergunta é "é possível?" não "é são?"
precisa saber é o seguinte

5
Qualquer código com esse tipo de "condições de corrida" é totalmente quebrado , independentemente de quantos núcleos você o execute. (Especialmente porque não há absolutamente nenhuma garantia quanto ao que outra pessoa está em execução no sistema.) Eu duvido seriamente que isso seja a causa, dada a facilidade com que ele iria tropeçar o jogo mesmo em um sistema hexacore ...
DevSolar

16

É improvável que esses "requisitos mínimos" representem algo abaixo do qual o jogo não será executado. Muito mais provável é que eles representem algo abaixo do qual o jogo não será executado com desempenho aceitável. Nenhuma empresa de jogos quer lidar com muitos clientes que reclamam de desempenho ruim quando o executam em uma única caixa de 1 Ghz, mesmo que o software possa tecnicamente ser executado. Portanto, eles provavelmente projetam deliberadamente falhas em caixas com menos núcleos do que lhes dariam um desempenho aceitável.

Uma métrica importante no desempenho do jogo é a taxa de quadros. Normalmente, eles são executados em 30 ou 60 quadros por segundo. Isso significa que o mecanismo do jogo precisa renderizar a visualização atual do estado do jogo em um período fixo de tempo. Para atingir 60 qps, há pouco mais de 16 ms para fazer isso. Jogos com gráficos de ponta são extremamente limitados à CPU e, portanto, há uma enorme troca entre tentar melhorar a qualidade (que leva mais tempo) e a necessidade de permanecer nesse orçamento de tempo. Assim, o orçamento de tempo para cada quadro é extremamente apertado.

Como o orçamento é curto, o desenvolvedor idealmente deseja acesso exclusivo a um ou mais núcleos. Eles provavelmente também querem poder fazer suas coisas de renderização em um núcleo, exclusivamente, pois é o que deve ser feito nesse orçamento de tempo, enquanto outras coisas, como o cálculo do estado mundial, acontecem em um processo separado, onde não são necessárias. intrometer.

Você poderia, em teoria, colocar tudo isso em um único núcleo, mas então tudo se torna muito mais difícil. De repente, você precisa garantir que todo o estado do jogo aconteça com rapidez suficiente e permita que a renderização ocorra. Você não pode simplesmente criar dois threads de software, porque não há como fazer com que o sistema operacional entenda "o thread A deve concluir uma quantidade X de trabalho em 16 ms, independentemente do segmento B".

Os desenvolvedores de jogos não têm interesse em fazer você comprar um novo hardware. A razão pela qual eles têm requisitos de sistema é que o custo do suporte a máquinas de gama baixa não vale a pena.


Embora isso seja verdade, acontece que você pode comprar hardware de núcleo duplo poderoso o suficiente para obter mais em um determinado período de tempo do que o hardware de núcleo quádruplo descrito nas especificações mínimas. Por que o fornecedor não listaria o hardware aceitável, uma decisão que só pode perder suas vendas?
Jules

4
A única coisa a comparar não é 2 x 4 núcleos. É essencialmente 1 versus 3 núcleos, já que a CPU nº 0 será praticamente vinculada ao driver gráfico e aos DPCs. Também existem efeitos significativos de cache e migração, se você assinar em excesso uma CPU com vários tipos de tarefas no sistema de tarefas de um jogo moderno típico. O requisito existe porque o Frostbite (mecanismo da DA: I) é projetado desde o início com um ajuste muito cuidadoso que requer um número específico de núcleos.
Lars Viklund

6
@LarsViklund Parece que você conhece mais detalhes do que qualquer outra pessoa aqui. Você já pensou em montar uma resposta?
Gort the Robot

11
"É improvável que esses" requisitos mínimos "representem algo abaixo do qual o jogo não será executado. Muito mais provável é que eles representem algo abaixo do qual o jogo não será executado com desempenho aceitável." - O G3258 da Intel é um processador dual core muito poderoso, amplamente usado por jogadores, capaz de executar jogos com recursos iguais ou mais intensivos que o Dragon Age Inquisition, mas muitos jogadores relatam que o jogo não roda nele.
uylmz

2
@Reek Duvido que um usuário final possa dizer com facilidade a intensidade de recursos de um jogo em particular em comparação com outro.
Gort the Robot

9

Três threads em tempo real que nunca dormem e um outro thread. Se houver menos de quatro núcleos, o quarto thread nunca será executado. Se o quarto encadeamento precisar se comunicar com um dos encadeamentos em tempo real para o encadeamento em tempo real, o código não terminará com menos de quatro núcleos.

Obviamente, se os encadeamentos em tempo real estiverem esperando algo que não lhes permita dormir (como um spinlock), o designer do programa estragou tudo.


11
Indiscutivelmente, quando um aplicativo solicita usuário realtime tópicos em primeiro lugar, o designer asneira: D
Luaan

2
Eu fiz isso. Meio milhão de linhas de código. Um caso usando cerca de 300 linhas. O encadeamento em tempo real passa a maior parte do tempo aguardando a entrada, para que possa registrar a data e hora da entrada e entregá-la a um encadeamento de menor prioridade.
Joshua

2
@Luaan Para a maioria dos aplicativos, eu concordo com você, mas os jogos são uma fera diferente, assim como os aplicativos incorporados. Em ambos os casos, a preocupação em se comportar bem com outros aplicativos simultâneos desaparece principalmente em favor do desempenho.
reirab

Embora não seria particularmente eficiente, esse cenário não levaria a quaisquer impasses - inversão de prioridade iria cuidar dela (assumindo que qualquer programador decente em qualquer grande sistema operacional da última década)
Voo

2
@ Josué > O Windows não sabe o que é inversão de prioridade. O que? support.microsoft.com/kb/96418 , msdn.microsoft.com/en-us/library/windows/desktop/ms684831.aspx . Além disso, inversão de prioridade é o termo que descreve o problema , não uma solução (@Voo).
Bob

3

Antes de tudo, os threads de software não têm nada a ver com os threads de hardware e geralmente são confusos. Os encadeamentos de software são partes de código que podem ser despachadas e executadas por si próprias no contexto do processo. Os threads de hardware são gerenciados principalmente pelo sistema operacional e são despachados para o núcleo do processador quando se fala de programas regulares. Esses threads de hardware são despachados com base na carga; o despachante de threads de hardware age mais ou menos como um balanceador de carga.

No entanto, quando se trata de jogos, especialmente jogos de ponta, às vezes os threads de hardware são gerenciados pelo próprio jogo ou o jogo instrui o despachante de threads de hardware sobre o que fazer. Isso ocorre porque todas as tarefas ou grupo de tarefas não têm a mesma prioridade, como em um programa normal. Como o dragon age vem de um estúdio de jogos de ponta que usa mecanismos de jogos de ponta, posso imaginar que ele usa expedição "manual" e, em seguida, o número de núcleos se torna um requisito mínimo do sistema. Qualquer programa falharia quando eu envio um pedaço de código para o terceiro núcleo físico em execução em uma máquina com apenas 1 ou 2 núcleos.


Este. Lembre-se de que dizer "não verificar núcleos" significa que uma empresa está fabricando seu software de uma maneira específica para forçar os usuários a comprar hardware mais caro (o que seria mal intencionado).
uylmz

2
Esses problemas existem enquanto houver jogos para PC. No começo, tínhamos 486dx e 486sx, depois o MMX e o não-MMX Pentium, core e non-core e hoje temos requisitos n-core. Essa é uma das razões pelas quais os consoles ainda existem.
dj Bazzie wazzie

4
Você tem uma referência para jogos assumindo o agendamento de CPU? Tanto quanto eu sabia, isso não é diretamente possível no Windows, pelo menos não de uma maneira que falharia da maneira que você sugere.
Jules

2
@djbazziewazzie, na verdade, o Windows fornece uma API para fazer exatamente isso, ou seja, defina um thread para sempre usar o mesmo núcleo; isso é chamado de afinidade de encadeamento e não permite selecionar manualmente qual parte do código é executada onde e quando, e não pode causar uma falha no sistema, como você sugere (o sistema ignorará uma solicitação para definir afinidade com um núcleo inexistente e continue agendando o encadeamento para qualquer núcleo quando ele estiver disponível.Tenho certeza de que é isso que a ID Tech usa, e isso realmente não significa "gerenciar os encadeamentos de hardware".
Jules

11
@djbazziewazzie Você também parece entender mal o ponto do Grand Central Dispatch, que não dá aos desenvolvedores mais controle sobre como o código está programado para um núcleo; de fato, seu objetivo é exatamente o oposto: escolher quantos encadeamentos criar e qual código deve ser executado em qual encadeamento das mãos dos aplicativos, para que possa ser otimizado para o hardware disponível em todo o sistema. A dependência de ter um certo número de núcleos é exatamente o tipo de problema que o GCD foi projetado para evitar.
Jules

1

Como é possível usar o virtualize para ter mais núcleos virtuais do que físicos, o software não saberia que está sendo executado em um virtualizador e, em vez disso, achar que ele possui muitos núcleos físicos, eu diria que esse software não é possível.

Ou seja, não é possível escrever um software que sempre pare com menos de N núcleos.

Como outros já apontaram, existem soluções de software que podem verificar potencialmente, especialmente se o sistema operacional e o código em uso tiver pouca proteção contra as condições de corrida quando N processos executam em processadores <N. O verdadeiro truque é o código que falhará quando você tiver menos de N processadores, mas não falhará quando você tiver N processadores, mas tiver um SO que possa atribuir trabalho a menos de N processadores.


1

Pode ser que haja três threads fazendo alguma coisa (gerando fundos ou gerando movimento do NPC) e passando eventos para um quarto, que deve agregar / filtrar os eventos e atualizar o modelo de exibição. Se o quarto encadeamento não receber todos os eventos (porque não está agendado em um núcleo), o modelo de exibição não será atualizado corretamente. Isso pode acontecer apenas esporadicamente, mas esses núcleos precisam estar disponíveis a qualquer momento. Isso pode explicar por que você não está vendo alto uso da CPU o tempo todo, mas o jogo não está funcionando adequadamente.


11
Nesse cenário, o jogo também falhava aleatoriamente quando os serviços em segundo plano eram agendados para execução, o que é bastante frequente na maioria dos computadores.
Jules

1

Acho que Joshua está seguindo o caminho certo, mas não para a conclusão.

Suponha que você tenha uma arquitetura em que há três threads escritos para fazer o máximo possível - quando terminam o que estão fazendo, o fazem novamente. Para manter o desempenho atualizado, esses encadeamentos não liberam o controle de nada - eles não querem arriscar o atraso do agendador de tarefas do Windows. Contanto que haja 4 ou mais núcleos, isso funcione bem, ele falhará se não houver.

Em geral, isso seria uma programação ruim, mas os jogos são outra questão - quando você se depara com uma escolha entre um design inferior em todo hardware ou um design superior em hardware suficientemente bom ou uma falha nos desenvolvedores de jogos de hardware inferior geralmente escolhem para exigir o hardware.


Geralmente, não é possível gravar um thread que não renuncie ao controle de outros threads. Todos os sistemas operacionais não RTOS modernos usam multitarefa preventiva, o que intencionalmente torna impossível para um encadeamento (modo de usuário) não liberar o controle de um determinado núcleo. Os threads do kernel, é claro, são uma questão diferente.
reirab

@reirab Aumente sua prioridade.
Loren Pechtel

@ Loren Não altera o fato de que o agendador ainda morre de trabalho, o que significa que você precisa compartilhar o tempo com outros threads da mesma prioridade e o agendador aumentando a prioridade dos threads com fome. Você não pode fazer isso em sistemas operacionais normais e, mesmo que pudesse, os jogos certamente também não seriam uma aplicação aceitável.
Voo

1

Is it possible to write code (or complete software, rather than a piece of code) that won't work properly when run on a CPU that has less than N number of cores?

Absolutamente. O uso de encadeamentos em tempo real seria um bom exemplo de uma situação em que essa é, não apenas possível, mas a maneira desejada (e geralmente a única maneira correta) de realizar o trabalho. No entanto, os encadeamentos em tempo real geralmente são limitados ao kernel do SO, geralmente para drivers que precisam garantir que um evento de hardware de algum tipo seja tratado dentro de um período definido. Você não deve ter threads em tempo real em aplicativos de usuário normais e não tenho certeza de que seja possível ter um em um aplicativo de modo de usuário do Windows. Geralmente, os sistemas operacionais tornam intencionalmente impossível fazer isso do local do usuário precisamente porque permite que um determinado aplicativo assuma o controle do sistema.

Em relação aos aplicativos de terra do usuário: Sua suposição de que a verificação de um determinado número de encadeamentos para execução seja necessariamente intencionalmente maliciosa não está correta. Por exemplo, você pode ter duas tarefas de longa execução e com alto desempenho que precisam de um núcleo para si mesmas. Independentemente da velocidade do núcleo da CPU, o compartilhamento de um núcleo com outros encadeamentos pode ser uma degradação séria e inaceitável do desempenho devido à interrupção do cache, além das penalidades normais decorrentes da troca de encadeamentos (que são bastante substanciais.) Nesse caso, seria perfeitamente razoável, especialmente para um jogo, defina cada um desses threads para ter afinidade apenas em um núcleo específico para cada um deles e defina todos os outros threads para não ter afinidade nesses 2 núcleos. Para fazer isso, no entanto, você '


1

Qualquer código que use spinlocks com uma quantidade notável de contenção de bloqueio terá um desempenho terrível (até um ponto em que - para um aplicativo como um jogo - você pode dizer "não funciona" ) se o número de threads exceder o número de núcleos.

Imagine, por exemplo, um encadeamento produtor enviando tarefas para uma fila que atenda a 4 encadeamentos do consumidor. Existem apenas dois núcleos:

O produtor tenta obter o spinlock, mas ele é mantido por um consumidor rodando no outro núcleo. Os dois núcleos estão executando o locktep enquanto o produtor está girando, aguardando a liberação do bloqueio. Isso já é ruim, mas não é tão ruim quanto será.
Infelizmente, o encadeamento do consumidor é quântico no final de seu tempo, portanto é antecipado e outro encadeamento do consumidor está agendado. Ele tenta se apossar da trava, mas é claro que a trava foi executada, agora dois núcleos estão girando e aguardando algo que não pode acontecer.
O encadeamento do produtor chega ao final do seu intervalo de tempo e é antecipado, outro consumidor acorda. Novamente, dois consumidores estão aguardando a liberação de um bloqueio, e isso não acontecerá antes que mais dois quantum de tempo tenham passado.
[...] Finalmente, o consumidor que estava segurando o spinlock liberou a trava. É imediatamente capturado por quem está girando no outro núcleo. Há uma chance de 75% (3 a 1) de ser outro segmento do consumidor. Em outras palavras, é 75% provável que o produtor ainda esteja parado. Obviamente, isso significa que os consumidores também param. Sem as tarefas de submissão do produtor, elas não têm nada a fazer.

Observe que isso funciona em princípio com qualquer tipo de bloqueio, não apenas spinlocks - mas o efeito devastador é muito mais proeminente com os spinlocks, porque a CPU mantém ciclos de gravação sem conseguir nada.

Agora imagine que, além do exposto acima, algum programador teve a brilhante idéia de usar um thread dedicado com afinidade definida no primeiro núcleo, para que o RDTSC proporcione resultados confiáveis ​​em todos os processadores (de qualquer forma, mas algumas pessoas pensam assim).


É por isso que bons spinlocks são rebaixados para outros tipos de bloqueios depois de um pequeno tempo, e os melhores ainda são mais rápidos se os usos anteriores do mesmo bloqueio tiverem que ser rebaixados.
Ian

-1

Se eu entendo o que você está perguntando, é possível, mas é uma coisa muito, muito ruim.

O exemplo canônico do que você está descrevendo seria manter um contador que é incrementado por vários threads. Isso requer quase nada em termos de poder de computação, mas exige uma coordenação cuidadosa entre os threads. Desde que apenas um encadeamento por vez faça um incremento (que na verdade é uma leitura seguida por uma adição seguida por uma gravação), seu valor sempre estará correto. Isso ocorre porque um thread sempre lê o valor "anterior" correto, adiciona um e escreve o valor "próximo" correto. Coloque dois threads na ação ao mesmo tempo e ambos lerão o mesmo valor "anterior", obterão o mesmo resultado do incremento e gravarão o mesmo valor "próximo". O contador terá sido efetivamente incrementado apenas uma vez, embora dois threads pensem que cada um deles fez isso.

Essa dependência entre tempo e correção é o que a ciência da computação chama de condição de corrida .

Geralmente, as condições de corrida são evitadas usando mecanismos de sincronização para garantir que os threads que desejam operar em um pedaço de dados compartilhados entrem na fila para acessar. O contador descrito acima pode usar um bloqueio de leitura e gravação para isso.

Sem acesso ao design interno de Dragon Age: Inquisition , tudo o que qualquer um pode fazer é especular sobre por que ele se comporta dessa maneira. Mas vou tentar com base em algumas coisas que já vi feitas em minha própria experiência:

Pode ser que o programa seja baseado em quatro threads que foram ajustados para que tudo funcione quando os threads forem executados principalmente - ininterruptamente em seus próprios núcleos físicos. O "ajuste" pode vir na forma de reorganizar o código ou inserir dormentes em locais estratégicos para mitigar os erros induzidos pelas condições de corrida que surgiram durante o desenvolvimento. Novamente, tudo isso é conjectura, mas vi as condições da corrida "resolvidas" dessa maneira mais vezes do que gostaria de contar.

A execução de um programa como esse em algo menos capaz do que o ambiente para o qual foi ajustado introduz alterações de tempo resultantes do código não ser executado tão rapidamente ou, mais provavelmente, de alternâncias de contexto. As alternâncias de contexto ocorrem nas formas física (ou seja, os núcleos físicos da CPU estão alternando entre o trabalho que seus núcleos lógicos estão mantendo) e lógica (ou seja, o sistema operacional na CPU está atribuindo trabalho aos núcleos), mas também é uma divergência significativa do que seria o tempo de execução "esperado". Isso pode trazer à tona o mau comportamento.

Se Dragon Age: Inquisition não der o simples passo de garantir que haja núcleos físicos suficientes disponíveis antes de continuar, a culpa é da EA. Eles provavelmente estão gastando uma pequena fortuna atendendo chamadas e e-mails de suporte de pessoas que tentaram rodar o jogo com pouco hardware.


11
Alguns jogadores dizem que isso é causado pelo DRM rodando em 2 núcleos e o jogo real também rodando em 2. Quando os threads do DRM e do jogo são executados no mesmo núcleo, fica confuso. Mas isso não me parece correto, pode ser uma pequena história inventada por um jogador que não sabe muito sobre arquitetura sw ou hw.
Ullmz

4
condições de corrida realmente não têm muito a ver com contagem de núcleos, -1 ... uma máquina de núcleo único com vários threads virtuais pode ter condições de corrida totalmente dependentes da técnica de redução de tempo do tempo de execução, ou um sistema com muitos núcleos pode evitar todas as condições de corrida sobre a forma estrita é com operações membar ...
Jimmy Hoffa

11
@Eek: Sem um conhecimento profundo de como o programa funciona, qualquer coisa é um palpite. Dois núcleos para fazer apenas o DRM parecem um pouco excessivos para mim.
Blrfl

11
@ JimmyHoffa: Eu discordo. Uma condição de corrida ainda é uma condição de corrida, mesmo quando não está causando comportamento indesejável. A contagem de núcleos pode influenciar se esse comportamento ocorre ou não, o que o questionador perguntou, mas eu não o citei como a única variável.
Blrfl

-1

O Windows possui uma funcionalidade interna para isso: a função GetLogicalProcessorInformation está na API do Windows . Você pode chamá-lo do seu programa para obter informações sobre núcleos, núcleos virtuais e hyperthreading.

Portanto, a resposta para sua pergunta seria: Sim.


3
Não estou perguntando "Posso descobrir nenhum dos núcleos do código?" ... Esse código será mal intencionado (obriga a comprar uma CPU mais cara para executar um programa - sem a necessidade de energia computacional).
Ullmz

3
Esta função fornece muito mais informações do que apenas um "número de núcleos" bruto. Com essas informações, você pode deduzir núcleos físicos, lógicos e muito mais. Se você pode deduzir isso, pode escrever um software para usar essas informações. De uma maneira boa ou ruim (programa de falha quando você vê 4 núcleos, mas menos de 4 núcleos físicos).
Pieter B

11
Isso pode funcionar no Windows, mas e OSX / Linux / iOS / Android / etc? Embora esteja referenciando um jogo como uma instância em que esse comportamento é visto (e a correlação natural seria Windows = Gaming), não parece ser uma solicitação específica do jogo.
Robert

Para um jogo como o Dragon Age, os sistemas em questão são Windows / XBox / PS4.
Gort the Robot

O Linux possui /proc/cpuinfoe sysconf(_SC_NPROCESSORS_ONLN)(o último sendo mencionado no POSIX). Usar as informações para impor um limite mínimo de desempenho ainda é uma péssima forma.
cHao
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.