¿Puedo atómicamente incrementar un contador de 16 bits en sistemas x86 / x86_64?
-
20-09-2019 - |
Pregunta
Quiero ahorrar memoria mediante la conversión de un contador de 32 bits existente a un contador de 16 bits. Este contador se incrementa atómicamente / decrementa. Si hago esto:
- ¿Qué instrucciones hacen que utilizo para atomic_inc (uint16_t x) en x86 / x86_64?
- ¿Es esta fiable en máquinas multi-procesador x86 / x86_64?
- ¿Hay una penalización de rendimiento para pagar en cualquiera de estas arquitecturas para hacer esto?
- Si es así para (3), ¿cuál es la penalización en el rendimiento esperado?
Gracias por sus comentarios!
Solución
Aquí hay una que utiliza extensiones de montaje del CCG, como una alternativa a la respuesta de Steve Delphi:
uint16_t atomic_inc(uint16_t volatile* ptr)
{
uint16_t value(1);
__asm__("lock xadd %w0, %w1" : "+r" (value) : "m" (*ptr));
return ++value;
}
Cambiar el 1 con -1, y el ++
con --
, por decremento.
Otros consejos
Esta es una función de Delphi que funciona:
function LockedInc( var Target :WORD ) :WORD;
asm
mov ecx, eax
mov ax, 1
Lock xadd [ecx], ax
Inc eax
end;
Creo que se puede convertir a cualquier idioma que necesite.
La forma más sencilla de realizar un aumento atómica es la siguiente (esto es ASM en línea):
asm
lock inc dword ptr Counter;
end;
donde J es un número entero. Esto aumentará directamente en contra de su posición de memoria.
He probado esto con la fuerza bruta y funciona 100%.
Para responder a las otras tres preguntas:
- No ha encontrado una manera de hacer una lista numerada a partir de 2
- Sí, esto es fiable en un entorno multiprocesador
- Sí, hay una penalización de rendimiento
- Las "LOCK" bloqueos de prefijos abajo los autobuses, no sólo para el procesador, pero para cualquier hardware externo, que puede que desee acceder al bus a través de DMA (almacenamiento masivo, gráficos ...). Por lo que es lento, por lo general ~ 100 ciclos de reloj, pero puede ser más costoso. Pero si usted tiene "megabytes" de los contadores, es probable, que se enfrentará a un fallo de caché, y en este caso, tendrá que esperar unos ~ 100 relojes de todos modos (el tiempo de acceso a memoria), en caso de un fallo de página, varias cien, por lo que la cabeza de bloqueo no podría ser importante.