Como está relacionado con el iPhone y el código de ensamblaje, daré un ejemplo que sería relevante en el mundo del iPhone (y no en algunos asse sse o x86). Si alguien decide escribir código de ensamblaje para alguna aplicación del mundo real, lo más probable es que se trate de algún tipo de procesamiento de señal digital o manipulación de imágenes. Ejemplos: conversión de espacio de color de píxeles RGB, codificación de imágenes al formato jpeg/png o codificación de sonido a mp3, amr o g729 para aplicaciones de voip. En caso de codificación de sonido hay muchas rutinas que no pueden ser traducidas por el compilador a código asm eficiente, simplemente no tienen equivalente en C. Ejemplos de las cosas comúnmente utilizadas en el procesamiento de sonido: matemática saturada, rutinas de acumulación múltiple, multiplicación de matrices .
Ejemplo de saturado agregar: 32-bit firm int tiene rango: 0x8000 0000 < = int32 < = 0x7fff ffff. Si agrega dos entradas, el resultado podría desbordarse, pero esto podría ser inaceptable en ciertos casos en el procesamiento de señales digitales. Básicamente, si el resultado se desborda o desborda saturada, add debe devolver 0x8000 0000 o 0x7fff ffff. Esa sería una función c completa para verificar eso. una versión optimizada del complemento saturada podría ser:
int saturated_add(int a, int b)
{
int result = a + b;
if (((a^b) & 0x80000000) == 0)
{
if ((result^a) & 0x80000000)
{
result = (a < 0) ? 0x80000000 : 0x7fffffff;
}
}
return result;
}
es posible que también se consiguen múltiples if/else para comprobar si hay desbordamiento o en x86 puede comprobar indicador de desbordamiento (que también requiere el uso de ASM). iPhone usa las CPU armv6 o v7 que tienen dsp asm. Por lo tanto, la función saturated_add
con múltiples brunches (sentencias if/else) y 2 constantes de 32 bits podría ser una instrucción asm simple que utiliza solo un ciclo de CPU. Por lo tanto, simplemente haciendo que la instrucción saturada use asm podría hacer que el algoritmo completo sea dos o tres veces más rápido (y de menor tamaño). Aquí está el manual QADD: otros QADD
ejemplos de código que a menudo ejecutan en bucles largos son
res1 = a + b1*c1;
res2 = a + b2*c2;
res3 = a + b3*c3;
parece que nada no puede ser optimizado aquí, pero en la CPU ARM puede utilizar instrucciones DSP específicos que ¡toma menos ciclos que para hacer una simple multiplicación! Así es, a + b * c con instrucciones específicas podría ejecutar más rápido que simple a * b. Para este tipo de casos, los compiladores simplemente no pueden entender la lógica de su código y no pueden usar estas instrucciones dsp directamente y es por eso que necesita escribir asm manualmente para optimizar el código, PERO solo debe escribir manualmente algunas partes del código que no necesitan ser optimizado ¡Si comienza a escribir bucles simples manualmente, es casi seguro que no le ganará al compilador! Hay varios documentos buenos en la web para el ensamblaje en línea para codificar filtros de abeto, codificación/descodificación de amr, etc.
No para molestarlo, pero hay muchísimas personas que piden optimización y preguntas de velocidad, y muy pocos dicen que lo necesitan porque no cumplen con los requisitos. Aparentemente no hemos vencido en la optimización prematura es la raíz de todo mal "mantra suficiente :) –
Lo que provocó mis preguntas fue que yo estaba dando vueltas con el montaje en línea en el iPhone y que iba a escribir una publicación en el blog sobre eso . Pero no pude por mi vida superar a mi compilador. Así que me llamó la atención ver si hay casos límite conocidos en los que los compiladores producen código ineficiente. –
El ensamblaje de ARM es uno de los conjuntos de instrucciones "más limpios". Parte de la filosofía de los procesadores RISC es no agregar instrucciones que no sean fácilmente utilizadas por el compilador. Tendría que mirar el conjunto de instrucciones de la variante de ARM particular y encontrar códigos de operación que no tienen una traducción clara de C. – NoMoreZealots