Você está na página 1de 8

Programacin eficiente en C para ARM Tcnicas Digitales II, UTN-FRBA, Ao 2009 Los siguientes conceptos de optimizacin de cdigo para

ARM fueron probados con el compilador propietario del software Keil Uvision3, Toolchain: Realview MDKARM Versin:3.80a. 1) Local Data Types Tipos de Variables locales: Siempre es conveniente trabajar con variables tipo int o long (ambos son de 32bits).

Justificacin: Existen instrucciones para el movimiento de datos de 8, 16 y 32bits. Sin embargo, los registros son de 32 bits y las operaciones se efectan en 32 bits. Esto genera programas ms largos. Ejemplos: a) c2=c1+c2;

/*Operaciones con char*/

Por cada operacin entre chars, se debe hacer una mscara para alojarlo en un registro de 32bits. b) s2=s1+s2;

/*Operaciones con short*/

La operacin entre short, es signada y debe trasladar bit 15 de signo hasta el bit 31 del registro de 32bits. Para operaciones de short sin signo, hace una mscara similar a como lo hace con los char. c) i2=i1+i2; ui2=ui1+ui2;

/*Operaciones con int*/ /*Operaciones con unsigned int*/

La operacin ms simple entre registros de 32 bits. 2) Function Argument Types Variables pasadas como argumentos de funciones: Siempre es conveniente pasar argumentos y devolver resultados con variables tipo int o long (ambos son de 32bits).

Programacin eficiente en C para ARM Tcnicas Digitales II, UTN-FRBA, Ao 2009 Justificacin: Cualquier tipo de argumento se pasa a travs de alguno de los registros de 32bits. Ser tarea del compilador agregar instrucciones de ms para manejar los argumentos como corresponde y entregar los resultados conforme al tipo de dato de salida. Esto genera programas ms largos. o todos los compiladores tienen el mismo comportamiento. Ejemplos: a) /*Funcin suma char*/ int suma_char(char c3, char c4) {c3=c3+c4; return (c3);} /*Llamado a la funcin*/ c1=suma_char(c1,c2);

Los argumentos se pasan en R0 y R1, como valores de 32bits. El retorno se hace a travs de R0, pero truncado a tipo char. b) /*Funcin suma short*/ short suma_short(short s3, short s4) {s3=s3+s4; return(s3);} /*Llamado a la funcin*/ s1=suma_short(s1,s2);

Los argumentos se pasan en R0 y R1, como valores de 32bits. El retorno se hace a travs de R0, pero truncado a tipo short. 3) Signed versus Unsigned Types Variables signadas o no signada: Siempre es conveniente emplear variables no signadas cuando se realicen operaciones matemticas complejas que incluyan, adems, divisiones.

Justificacin:

Programacin eficiente en C para ARM Tcnicas Digitales II, UTN-FRBA, Ao 2009 Si bien las divisiones y multiplicaciones por 2 se logran con un desplazamiento, no es vlida esta estrategia cuando son variables signadas. Por otro lado, las familias ARM7 no incluyen el hardware para realizar divisiones, por lo tanto, se realiza por soft. Una divisin con signo deber recurrir a una rutina de mayor cdigo y tardar ms. Ejemplos: a) ui1=ui1/4;

/*Divisin sin signo por Barrel Shifter*/

i1=i1/4; /*Divisin con signo por Barrel Shifter*/

Se genera un cdigo ms extenso en la divisin por potencias de 2 cuando se trabaja con variables signadas. a) ui1=ui1/ui2;

/*Divisin sin signo*/

i1=i1/i2;

/*Divisin con signo*/

Se ejecutan por software a travs de dos rutinas diferentes: Symbol Size __aeabi_idivmod 0x00000214 ARM Code 384 __aeabi_uidivmod 0x00000600 ARM Code 28 El tiempo de ejecucin para la rutina sin signo es del 85% de la rutina con signo. 4) C looping structures Bucles: Siempre emplear variables de control del bucle en forma descendente e independiente, que finalicen el bucle cuando se hacen cero. Para bucles que tienen como mnimo un ciclo, emplear do - while en vez de for.

Programacin eficiente en C para ARM Tcnicas Digitales II, UTN-FRBA, Ao 2009 Agrupar ciclos, en un ciclo ms extenso, pero que no rompe el Pipeline.

Justificacin: Existe el ya conocido flag de Zero que evita todo tipo de comparacin a la hora de finalizar un bucle. Cuando se emplean bucles for, se generan ms lneas de cdigo al inicio del bucle, que al ser un bucle de ms de un ciclo, son innecesarias y extienden el tiempo total del bucle. Cualquier tipo de salto en una arquitectura ARM rompe el Pipeline, es decir, la prxima instruccin no se ejecutar hasta no llegar a la etapa de ejecucin del Pipeline. Por lo tanto, por cada ciclo (salto al inicio) se estarn perdiendo ciclos donde el micro no ejecuta ninguna instruccin, sino que se prepara para ejecutarla. IMPORTANTE: Estas optimizaciones se lograron al configurar al compilador en nivel de optimizacin -02. Ejemplos: a) for (i=0;i<10;i--){ui1++;} for(i=10;i!=0;i--)

La diferencia se ve en la instruccin de ms que se debe hacer para comparar contra 10 en el primer caso. El segundo caso, la instruccin SUBS activa el flag de cero en caso de que la resta cumpla esta condicin. b) for (i = n;i = 0; i--){ui1++;} i=n; do{

ui1++;}while(--i);

El primer caso realizado con un for, agrega dos instrucciones al inicio del bucle para verificar si la variable n es distinta de cero. c) i=n/2;

Programacin eficiente en C para ARM Tcnicas Digitales II, UTN-FRBA, Ao 2009 do{ ui1++; u1++;}while(--i);

En este loop tan sencillo, podemos reducir los saltos, implementando un bucle que se ejecuta la mitad de veces, pero cada ciclo hace el doble de la operacin. Es un ejemplo sencillo y casi sin sentido, pero demuestra la idea de la tcnica denominada Loop Unrolling. 5) Structure Arrangement Estructuras de datos: Siempre emplear estructuras de datos con pocas variables y preferentemente todas del mismo tipo de dato. Cuando lo anterior no sea posible y deban utilizarse estructuras que contienen distintos tipos de datos, ordenarlos en orden creciente a sus tamaos, es decir, primero los char, luego short, seguido los int o long y finalmente los long long. Es aconsejable que se reserven espacios en blanco para alinear correctamente las variables dentro de la estructura, y no dejar sta tarea al compilador.

Justificacin: Los compiladores alinean las variables dentro de la estructura en base al tipo de dato. Los char se ubican en posiciones de memoria 0xX, los short en posiciones 0xX0 y los int o long en posiciones 0xX00. Si una estructura contiene varios tipos de datos y en forma desordenada, el compilador completar con espacios en blanco las posiciones de memoria intermedias para cumplir con el alineamiento. aturalmente se esta desperdiciando espacio de memoria. Si el ordenamiento de variables se hace manualmente o se acomodan correctamente las variables contenidas en la estructura, entonces se desperdiciar menos espacio. Ejemplos: a) Definimos una estructura: struct { char a; int b; char c;

Programacin eficiente en C para ARM Tcnicas Digitales II, UTN-FRBA, Ao 2009 short d; } s; Cargamos los valores para ver como queda el mapa de memoria: s.a=0xFF; s.b=0xFFFFFFFF; s.c=0xFF; s.d=0xFFFF; Cdigo generado Mapa de memoria

E n el cdigo generado, en R1 se carga inicialmente la base de la estructura y luego se emplean las instrucciones STR, STRB o STRH para ir guardando el tipo de dato int, char o short segn corresponda. Se ve claramente en el mapa de memoria como se desperdicia espacio rellenado con cero, como consecuencia de la alineacin de las variables dentro de la estructura. b) Definimos la misma estructura, pero ahora mejor ordenada: struct { char a; char c; short d; int b; } s; s.a=0xFF; s.c=0xFF; s.d=0xFFFF; s.b=0xFFFFFFFF;

Cdigo Generado

Mapa de memoria

Programacin eficiente en C para ARM Tcnicas Digitales II, UTN-FRBA, Ao 2009

Es esperable que el cdigo generado tenga offsets distintos, pero es notable que la estructura ocupa menos espacio de memoria. 6) Bit Fields Campo de Bits: o emplear campos de Bits, es cambio, utilizar variables tipo int e interpretar cada bit en forma independiente y usando extensivamente mscaras.

Justificacin: Por la misma razn que el item 1, todo tipo de operacin requiere necesariamente que los operandos se encuentren en alguno de los registros de 32bits, no hay posibilidad de aislar un bit y es ms eficiente utilizar mscaras como operando para evaluar un bit dentro de una variable tipo int. 7) Divisiones: Minimizar al mximo las operaciones de divisin. Preferentemente que el numerador y el denominador sean variables no signadas o que alguno de ellos sea una constante.

Justificacin: Las familias de microcontroladores ARM7 no tienen la lgica que resuelva por hardware las divisiones, por lo tanto toda divisin invocar inevitablemente a una subrutina para cumplir con la operacin. La rutina necesaria variar en funcin del tipo de variable, signada o no, y en consecuencia se tendrn dos comportamientos ditintos. Existen algoritmos dedicados a optimizar las divisiones, por ejemplo transformar una divisin en una multiplicacin, y son mucho mas eficientes si se los trabaja con valores constantes. El ejemplo referido a las divisiones es el mismo que se present en la seccin 3 de este apunte.

Programacin eficiente en C para ARM Tcnicas Digitales II, UTN-FRBA, Ao 2009 Bibliografa: ARM System Developers Guide Designing and Optimizing System Software. Andrew N. Sloss, Dominic Symes & Chris Wright. Elsevier.

Você também pode gostar