Respostas:
Para obter ganhos de desempenho, as CPUs modernas geralmente executam instruções fora de ordem para aproveitar ao máximo o silício disponível (incluindo leitura / gravação de memória). Como o hardware impõe a integridade das instruções, você nunca percebe isso em um único encadeamento de execução. No entanto, para vários encadeamentos ou ambientes com memória volátil (E / S mapeada na memória, por exemplo), isso pode levar a um comportamento imprevisível.
Uma barreira / barreira de memória é uma classe de instruções que significa que as leituras / gravações de memória ocorrem na ordem que você espera. Por exemplo, uma 'vedação completa' significa que todas as leituras / gravações antes da vedação são confirmadas antes daquelas após a vedação.
Observe que cercas de memória são um conceito de hardware. Em linguagens de nível superior, estamos acostumados a lidar com mutexes e semáforos - eles podem muito bem ser implementados usando cercas de memória de baixo nível e o uso explícito de barreiras de memória não é necessário. O uso de barreiras de memória requer um estudo cuidadoso da arquitetura do hardware e mais comumente encontrado em drivers de dispositivo do que no código do aplicativo.
A reordenação da CPU é diferente das otimizações do compilador - embora os artefatos possam ser semelhantes. Você precisa tomar medidas separadas para interromper o compilador reordenando suas instruções, se isso puder causar um comportamento indesejável (por exemplo, uso da palavra-chave volátil em C).
Copiando minha resposta para outra pergunta: Quais são alguns truques que um processador faz para otimizar o código? :
O mais importante seria reordenar o acesso à memória.
Se não houver cercas de memória ou instruções de serialização, o processador poderá reordenar os acessos à memória. Algumas arquiteturas de processador têm restrições sobre o quanto elas podem reordenar; O alfa é conhecido por ser o mais fraco (ou seja, aquele que pode reordenar mais).
Um tratamento muito bom do assunto pode ser encontrado na documentação de origem do kernel do Linux, em Documentation / memory-bars.txt .
Na maioria das vezes, é melhor usar as primitivas de bloqueio do seu compilador ou biblioteca padrão; elas são bem testadas, devem ter todas as barreiras de memória necessárias e provavelmente são bastante otimizadas (otimizar as primitivas de bloqueio é complicado; até os especialistas podem errar algumas vezes).
Alpha is known for being the weakest
, por quê weakest
? Não é melhor que, reorganize mais, de modo que a execução será muito mais rápida? (Eu não sou usuário alfa, mas perguntando sobre o efeito de very reordering
vs restricted reordering
). Portanto, quais são as desvantagens da reorganização de lotes (exceto o risco de comportamento indefinido, mas eu acho que a maioria das CPUs modernas deveria ter resolvido boas reordenações e implementado apenas reordenações definidas, caso contrário, isso não faria sentido na decisão que elas tomaram).
Na minha experiência, refere-se a uma barreira de memória , que é uma instrução (explícita ou implícita) para sincronizar o acesso à memória entre vários threads.
O problema ocorre na combinação de compiladores agressivos modernos (eles têm uma incrível liberdade para reordenar instruções, mas geralmente não sabem nada sobre seus threads) e CPUs multicore modernas.
Uma boa introdução ao problema é a " Declaração de 'O bloqueio duplo verificado está quebrado' ". Para muitos, foi o chamado de alerta que havia dragões.
Barreiras implícitas à memória total são geralmente incluídas nas rotinas de sincronização de encadeamentos da plataforma, que cobrem o núcleo. No entanto, para programação sem bloqueio e implementação de padrões de sincronização leves e personalizados, muitas vezes você precisa apenas da barreira, ou mesmo apenas de uma via.
A barreira da memória, também conhecida como membar ou barreira de memória, é uma classe de instruções que fazem com que uma unidade central de processamento (CPU) imponha uma restrição de pedido às operações de memória emitidas antes e depois da instrução de barreira.
As CPUs empregam otimizações de desempenho que podem resultar em execução fora de ordem, incluindo operações de carregamento e armazenamento de memória. A reordenação da operação de memória normalmente passa despercebida em um único encadeamento de execução, mas causa comportamento imprevisível em programas simultâneos e drivers de dispositivo, a menos que seja cuidadosamente controlado. A natureza exata de uma restrição de pedido depende do hardware e é definida pelo modelo de memória da arquitetura. Algumas arquiteturas fornecem várias barreiras para impor restrições de pedidos diferentes.
Barreiras de memória são normalmente usadas na implementação de código de máquina de baixo nível que opera na memória compartilhada por vários dispositivos. Esse código inclui primitivas de sincronização e estruturas de dados sem bloqueio em sistemas multiprocessadores e drivers de dispositivo que se comunicam com o hardware do computador.