Herramientas de Programación

Curso 2003-2004

Práctica 3: Control de versiones con CVS y profiling

En esta práctica tenemos dos partes diferenciadas:

Una primera parte en la que se trata de ilustrar el uso de una herramienta de mantenimiento de versiones, concretamente CVS, mostrando su uso integrada en el entorno de desarrollo KDE y también desde la línea de órdenes. Y, la segunda que está orientada a la mejora de la eficiencia de los programas

   
Parte 1: Gestión de versiones compartidas con CVS

Crear un nuevo proyecto en KDevelop, tipo "Personalizado", y darle soporte para CVS cuando lo pregunte. Recordar el nombre que se le pone al proyecto, y dónde se deja el repositorio. Añadir a él (con "Añadir ficheros existentes") todos los archivos que se encuentran en /iilabs/HP/PRAC4/gocr/gocrmin.  Crear un makefile en el directorio más interno del proyecto cuyo objetivo es crear una biblioteca estática con todos los archivos fuente, excepto gocr.c, y el ejecutable gocr que se construirá compilando gocr.c y enlazando con la biblioteca. Se deben añadir opciones para buscar los archivos de cabecera en el propio directorio y en /usr/X11R6/include, y para que se defina la constante HAVE_CONFIG_H. Además, el ejecutable deberá enlazar con la biblioteca recién creada, y con bibliotecas que se encuentran en /usr/local/netpbm/lib. Finalmente, crear también el Makefile del directorio superior, para que llame al del interno. Probar a compilar y ejecutar, usando como argumento a gocr el archivo imre.pnm. gocr es un reconocedor de caracteres, que muestra por pantalla texto ASCII con el contenido de los caracteres que se encuentran en el archivo gráfico (el cual, por cierto, se puede visualizar, p. ej. con xv).

Supongamos dos programadores diferentes, A y B.

Imaginad que sois A, y añadid los archivos de cabeceras y fuentes, así como los Makefiles, al repositorio.  Para ello, en la ventana izquierda de KDevelop, situaros sobre cada archivo y pulsad sobre él, eligiendo la opción adecuada del menú que aparece.  Si esto resulta laborioso, en una línea de órdenes ir al directorio de los archivos y ejecutar la orden de añadir de cvs usando comodines. A continuación, confirmar cada archivo del mismo modo, o desde la línea de órdenes. cvs asignará a esta primera versión el número de versión 1.1. Se pueden ver los
archivos creados en los subdirectorios CVS; se puede apreciar que KDevelop ha incluído las entradas de todos nuestros archivos, y además las de todos los archivos creados por él para la gestión del proyecto.

Salid de KDevelop. Moved el directorio principal del proyecto a otro (digamos, nombre.old). Este directorio de trabajo no se volverá a usar hasta un apartado posterior.

Ahora imaginad que sois B. Extraed del repositorio el directorio de trabajo; usar para ello CVS desde la línea de órdenes. Abrid KDevelop, y sustituir los archivos pixel.c y gocr.h por los que se encontrarán en /iilabs/HP/PRAC4/gocr/gocrsus, usando "Añadir ficheros existentes" y confirmando la sobreescritura de los actuales. Nótese que, de no estar usando cvs, éstos se habrían perdido irremisiblemente. Confirmad los cambios para los archivos sustituídos; cada uno de ellos pasará ahora a estar en versión 1.2.  Verificad los cambios que se han producido usando las órdenes diff, log y status de cvs desde la línea de órdenes.

Vamos ahora a cambiar el archivo fuente principal por otro. Para ello, añadid al proyecto el archivo recon.c de /iilabs/HP/prac2/gocrsus, y eliminar del proyecto el gocr.c. Modificad apropiadamente el (los) Makefiles. Usar las órdenes pertinentes de CVS para añadir al repositorio el nuevo archivo, y eliminar del repositorio el que ya no queremos, así como el (los) Makefiles. Confirmad los cambios; estos cambios constituyen la versión 1.2 de los archivos cambiados. Verificad los cambios efectuados entre cada una de las versiones usando como antes diff, log y status.

Imaginad ahora que sois A de nuevo. A va a cambiar el programa. Para ello, salid de KDevelop, id al directorio nombre.old donde está la versión obsoleta (que para A, es la que él conoce) y actualizadla. Observad lo que ha sucedido en el repositorio con el archivo gocr.c borrado.

Ahora:

1) Cambiad alguna de las funciones en alguno de los archivos fuente del directorio de A, y confirmad los cambios.

2) A continuación, imaginad que sois otra vez B; cambiad otra función del mismo archivo en el directorio que B extrajo, y confirmad el cambio.

3) Finalmente, de nuevo sois A. Id al directorio nombre.old, actualizad todo y ved qué ha ocurrido con el archivo cambiado.

Repetid los pasos 1 a 3, pero con la misma línea del mismo archivo. Observad lo que sucede cuando B intenta confirmar.

Por último, realizad una copia de seguridad del repositorio con la orden tar; compilad el programa, y realizad una copia de seguridad también con tar del directorio de trabajo. Comparad los tamaños de ambas.

 

 

Parte 2: Eficiencia, precisión y tiempos de ejecución (gprof)

El objetivo de esta parte es realizar implementaciones lo más eficientes que sea posible de ciertas funciones matemáticas.

Se deberá crear con Kdevelop un nuevo proyecto, tipo C++ en terminal, y añadir a él los ficheros .h y .cpp que se encuentran en el directorio /iilabs/HP/PRAC3/ej3. El programa sirve para crear tablas con los valores de cualquier función que se haya programado, para valores comprendidos entre un valor inicial y un valor final dados y a intervalos de cierto incremento, también dado.

Deberá tomarse como ejemplo la función
$f(x)=ax^2+bx+c$
que se encuentra implementada en los ficheros cuadrado.h y cuadrado.cpp, y a semejanza de ella hacer otras. Para añadir una nueva función, digamos mifuncion, hay que:

  • Crear los ficheros mifuncion.h y mifuncion.cpp con la cabecera y la implementación. El prototipo deberá ser de la forma
    numtip mifuncion(numtip x, (otros parámetros, si los hay) );
    donde numtip ha sido definido en funciones.h como uno de los tipos float, double o long double.

  • Editar funciones.h añadiendo una constante de entero con un número que identificará la función, y añadir al array de strings nomfun un lugar más y un nombre para la función.

  • Editar tabla.cpp para incluir mifuncion.h y añadir una etiqueta más al switch de la función tabla::llenar. Hacerlo prácticamente igual que el case de la función cuadrado que ya está.

  • Editar main.cpp y añadir una llamada a la nueva función para que cree una tabla y la llene con sus valores. Hacerlo igual que la que ya está.

Las funciones que hay que implementar son:

  • La función de Bessel de tipo 0, definida como:
    $J_0(x)=\sum_{k=0}^{\infty} \left(\frac{x}{2}\right)^{2k}\frac{1}{{k!}^2}$ y hacer su tabla entre 0 y 5 a intervalos de 0.01

Hay que comparar los resultados si se usa como tipo numérico float, double o long double, y ver si hay pérdida de precisión. También hay que comparar los tiempos de ejecución usando gprof para cada función, según la implementación más o menos eficiente que se haya hecho, y según el tipo de datos usado. Para ello en el menú Proyecto-Opciones-Compilador de KDevelop activar la opción de generar información para gprof. Al ejecutar el programa se generará en su directorio el fichero gmon.out; supongamos que el programa se llama tabfun. En ese caso, ejecutando
   gprof tabfun gmon.out > salida
se obtiene un fichero salida en el que aparece información detallada sobre los tiempos de ejecución empleados por cada llamada, y una interpretación de lo que significan dichos números.