Posso incrementar atomicamente um contador de 16 bits em x86/x86_64?
-
20-09-2019 - |
Pergunta
Quero salvar a memória convertendo um contador de 32 bits existente em um contador de 16 bits. Este contador é incrementado/diminuído atomicamente. Se eu fizer isso:
- Que instruções eu uso para atomic_inc (uint16_t x) em x86/x86_64?
- Isso é confiável nas máquinas multiprocessador x86/x86_64?
- Existe uma penalidade de desempenho a pagar em alguma dessas arquiteturas por fazer isso?
- Se sim, para (3), qual é a penalidade de desempenho esperada?
Obrigado por seus comentários!
Solução
Aqui está um que usa extensões de montagem do GCC, como uma alternativa à resposta Delphi de Steve:
uint16_t atomic_inc(uint16_t volatile* ptr)
{
uint16_t value(1);
__asm__("lock xadd %w0, %w1" : "+r" (value) : "m" (*ptr));
return ++value;
}
Altere o 1 com -1 e o ++
com --
, para diminuir.
Outras dicas
Aqui está uma função Delphi que funciona:
function LockedInc( var Target :WORD ) :WORD;
asm
mov ecx, eax
mov ax, 1
Lock xadd [ecx], ax
Inc eax
end;
Eu acho que você poderia convertê -lo em qualquer linguagem que você precisar.
A maneira mais simples de realizar um aumento atômico é a seguinte (este é em linha ASM):
asm
lock inc dword ptr Counter;
end;
onde j é um número inteiro. Isso aumentará diretamente o contador em seu local de memória.
Eu testei isso com força bruta e funciona 100%.
Para responder às outras três perguntas:
- Não encontrou uma maneira de fazer uma lista numerada começando com 2
- Sim, isso é confiável em um ambiente multiprocessador
- Sim, há uma penalidade de desempenho
- O prefixo "bloqueio" trava os ônibus, não apenas para o processador, mas para qualquer hardware externo, que pode querer acessar o barramento via DMA (armazenamento em massa, gráficos ...). Portanto, é lento, normalmente ~ 100 ciclos de relógio, mas pode ser mais caro. Mas se você tem "megabytes" de contadores, é provável que você esteja enfrentando uma falta de cache e, neste caso, você terá que esperar cerca de 100 relógios de qualquer maneira (o tempo de acesso à memória), em caso de uma página, vários, vários Centenas, então a sobrecarga da trava pode não importar.