arm - procesador - ¿Por qué los tipos sin firmar son más eficientes en la CPU de brazo?
principales marcas de procesadores (4)
Creo que es solo que el conjunto de instrucciones para las CPU ARM está optimizado para unsigned. Algunas operaciones pueden realizarse con una instrucción para tipos sin firmar, pero necesitarán varias instrucciones si están firmadas. Es por eso que creo que si se compila para ARM en la mayoría (¿todos?) De los compiladores C y C ++, el valor predeterminado es char sin signo en lugar del carácter de signo más habitual.
Estoy leyendo un manual de brazo y tomo esta sugerencia, pero la razón no se menciona.
¿Por qué los tipos sin firmar son más rápidos?
Las únicas ventajas de los tipos sin firmar que puedo pensar son que las implementaciones de división y módulo pueden ser ligeramente más rápidas, y puedes hacer pruebas como if (unsigned_value < limit)
lugar de if (signed_value >= 0 && signed_value < limit)
.
Sospecho que su manual puede estar desactualizado. Cualquier ARM en uso hoy tendrá v4 o posterior del conjunto de instrucciones, y estoy bastante seguro de que las instrucciones no son más rápidas o más lentas según el firmado.
En los ARM más antiguos, creo que la multiplicación firmada podría ser más lenta; Creo que la terminación anticipada solo buscaba todos los ceros en los bits superiores, no en todos, por lo que las multiplicaciones que implican números negativos siempre tomarían el tiempo máximo. Aunque esto dependía del valor, no de si el tipo estaba firmado o no. Al menos ARMv4 y posterior, la terminación anticipada funciona para valores negativos.
Además, creo que los ARM muy antiguos no podían cargar un solo byte, solo una palabra. Por lo tanto, necesitaría dos instrucciones para cargar un byte sin firmar, y tres para cargar una firmada:
ldr r0, [r1]
and r0, r0, #0xff
versus
ldr r0, [r1]
mov r0, r0, asl #24
mov r0, r0, asr #24 ; but this could maybe be combined with later instructions
versus (en estos días) ldrb r0, [r1]
o ldrsb r0, [r1]
para hacer una carga de un solo byte.
En un procesador moderno, es muy poco probable que el uso de tipos sin signo tenga un impacto mensurable en el rendimiento. Utilice el tipo que tenga más sentido, luego mire el código en detalle una vez que haya identificado los cuellos de botella de rendimiento.
Antes de ARMv4, ARM no tenía soporte nativo para cargar halfwords y bytes firmados. Para cargar un byte con signo, tenía que LDRB
luego firmar extender el valor ( LSL
arriba y luego volver a ASR
). Esto es doloroso así que char
unsigned
está unsigned
por defecto.
En ARMv4, las instrucciones se agregaron para manejar halfwords y valores firmados. Estas nuevas instrucciones tuvieron que ser exprimidas en el espacio de instrucción disponible. Los límites en el espacio disponible significaban que no podían ser tan flexibles como las instrucciones originales, que pueden hacer varios cálculos de direcciones al cargar el valor.
Por lo tanto, puede encontrar que LDRSB
, por ejemplo, no puede combinar una recuperación de la memoria con un cálculo de direcciones, mientras que LDRB
podría. Esto puede costar ciclos. A veces podemos volver a trabajar código short
para operar en pares de ints
para evitar esto.
Hay más información en mi sitio aquí: http://www.davespace.co.uk/arm/efficient-c-for-arm/memaccess.html
Las respuestas de esta pregunta pueden ayudarte.