miércoles, 23 de mayo de 2012

[CÓMPUTO INTEGRADO] Consejos y técnicas de optimización

Cuando realizé mi proyecto PIC, este trataba sobre calcular los primos de 0 a 255 y me vi en un gran lio con el algoritmo para calcular los primos, ya que, aunque no hay que subestimar el poder de uno de esos microcontroladores, la memoria es un factor importante para el correcto funcionamiento de una rutina en un PIC.

Existen algoritmos para calcular los primos, pero involucran un gran gasto de memoria, así que pondré las etapas por las que pasé para resolver el problema.

1. Memoria

La memoria es el factor importante como se mencionó antes, así que para hacer un proyecto con PICs siempre hay que tener en cuenta un estimado de la memoria que podría usar, para poder escoger el microcontrolador adecuado.

En caso de que tu proyecto dependa de un microcontrolador específico pero la memoria sea insuficiente, puedes utilizar memorias EEPROM mediante el protocolo I2C. Proporcionan memoria adicional y la comunicación es sencilla.

La plataforma Arduino tiene librerías para el manejo de memorias EEPROM y flash, por lo que es mucho más sencillo su uso.

En mi caso, no tuve problemas con la memoria ya que mi algoritmo fue simple al final.

2. Código

Lo siguiente en la lista es el código que ejecuta. Quizá el problema no sea la memoria insuficiente, quizá sea que el código simplemente no esté bien optimizado, este fue el primer problema que tuve, ya que el primer algoritmo que utilizé no era del todo óptimo.

Al principio utilizé MPASM, pero luego me cambié a MikroBasic, luego hablaremos de los lenguajes. Debido a que en MPASM no existen operadores matemáticos más grandes que la suma y la resta mi algoritmo se basó en restas:

Si por ejemplo tengo un 9, le digo a mi programa que a 9 le reste 9-1

  • 9 - (9 - 1) = 1
Si el resultado es menor a 9 - 1 se resta 1 a 9 - 1 y ahora es 9 - 2, se repite el proceso hasta que el resultado sea mayor que 9 - el número que le toque. De ser así sucede lo siguiente:
  • 9 - (9 - 5) = 5 ---> 5 - (9 - 5) = 1
Se sigue hasta que el número que se resta sea un número 2 unidades menor que 9, en este caso 7, después de eso, se acaba y sigue con el siguiente número a saber si es primo o no.

De encontrar un 0 de resultado en este proceso, se sale del ciclo y le dice al programa que el número NO es primo, de llegar al final sin 0 entonces e programa sabe que el número es primo

Al pasarme a MikroBasic, encontré las multiplicaciones y divisiones, inclusive encontré la función para sacar el módulo sin la necesidad de hacer una división.

Mi algoritmo cambió de hacer largas restas a buscar un módulo y saber si es 0 o no:
  • Se pasan directamente los números 0, 1, 2, 3, 5 y 7
  • Se saca el módulo del número dividido entre  2
    • Es 0?; SI, se sale y anuncia que no es primo; NO, continua
  • Se saca el módulo del número dividido entre 3
    • Es 0?; SI, se sale y anuncia que no es primo; NO, continua
  • Se saca el módulo del número dividido entre 5
    • Es 0?; SI, se sale y anuncia que no es primo; NO, continua
  • Se saca el módulo del número dividido entre 7
    • Es 0?; SI, se sale y anuncia que no es primo; NO, el número es primo
De ambos, el segundo parece más óptimo, ya que solo usa unas cuantas condiciones, en cambio el primero  parece que llenará la memoria con restas y más restas.

La verdad, MikroBasic al traducir el código a un .hex realizará lo mismo que hice al principio, solo que agregará cosas que no se habían contemplado, ya que después de todo, los microcontroladores funcionan con puras sumas y restas. Se puede decir que la primera idea pudo ser mejor que la segunda de haberla escrito en forma más organizada y mejor planteada.

Como recomendación, siempre hay que utilizar lo que nos ofrezca  una mayor optimización aunque esto requiera de escribir y pensar un poco más.

3. Lenguaje

La tercera cosa más importante que yo considero es la selección del lenguaje. En mi proyecto yo utilicé el lenguaje MikroBasic, ya que es muy practico para pequeños proyectos, pero si nuestro poryecto consiste en ahorrar memoria y realizar operaciones matemáticas muy largas, recomendaría, desde mi punto de vista, utilizar MPASM.

Con MPASM tenemos control total de la memoria y es cosa de nosotros como la utilizaremos. Podemos utilizar y reutilizar registros, etc.

Los lenguajes de más alto nivel son útiles si no tenemos experiencia con assembler (como yo), pero incluso el mismo lenguaje nos permite escribir parte del código en assembler.

Las ventajas de MPASM:
  • Set de instrucciones fácil de comprender.
  • Control total de los recursos.
  • Más óptimo.
Las desventajas de MPASM:
  • El código se vuelve difícil de comprender al escribir varias lineas.
  • Solo hay 2 operandos, suma y resta.
  • Hay que portar el código de un microcontrolador a otro.
Las ventajas de lenguajes de alto nivel:
  • Fácil uso.
  • Disponemos de todos los operandos.
  • Portabilidad entre microcontroladores muy practica.
  • Detección y solución de errores más práctica.
Las desventajas de lenguajes de alto nivel:
  • El .hex resultante no es del todo optimizado.
  • No sabemos como queda distribuido el uso de la memoria.
Estos 3 temas son importantes a la hora de hacer nuestro proyecto PIC, Arduino o inclusive algun programa de computadora que requiera de optimización de memoria.

1 comentario: