martes, 28 de enero de 2014

Comenzando el año

Antes que otra cosa quiero desearles un prospero año nuevo.

Comenzamos el año con nuevos proyectos, metas y ganas de hacer algo productivo (aún más). Este año sí mantendré más actualizado mi blog y no es promesa típica de año nuevo (como las dietas, metas irreales, etc). El asunto de la paternidad me ha tenido ocupado, sí ya soy padre de un hermoso niño que tiene 10 meses, pesa unos 12 Kgs y es muy inquieto.

Por ahí les tengo el resultado de la decisión que tomé entre Fedora y Manjaro, además estoy aprendiendo Qt usando C++ (ya sé C++, pero no había usado Qt), además esto se puede integrar con Python también, que como ya saben es mi lenguaje predilecto.

No creo que escriba algo muy avanzado de Qt, obviamente estoy comenzando con todo ese proceso, sin embargo espero retomar los artículos de programación paralela, retocarlos donde haga falta y continuar con la serie:

Parte 1
Parte 2

Saludos y éxito.

martes, 25 de junio de 2013

Dejando Ubuntu

Para ser más específico, Xubuntu, es la distro que uso actualmente y que estoy a punto de abandonar ¿Por qué? ¿a cual me cambio? De eso se trata este artículo.

Como ya saben, quienes leyeron la primera entrada del blog,  mi trabajo principalmente es como programador, aunque también estoy a cargo de algunos servidores, pero mi rama principal es el desarrollo de aplicaciones  por ello me gusta una distribución que sea simple de usar, rápida y sobre todo estable. Para ser más eficiente necesito una distro que me permita enfocarme en lo que realmente es mi trabajo y no en mantenerla funcionando.

Mi historia con Ubuntu comienza con la versión 5.04, mi distro de escritorio era Suse (antes de ser OpenSuse), pero Ubuntu me pareció tan genial que decidí adoptarla para mi uso diario (aunque no tenía quejas de Suse). Con el tiempo comencé a contribuir reportando bugs, usaba las primeras alfas, las betas y podía ver la evolución de las distintas versiones.

Al pasar el tiempo comienzo a notar que en cada nueva versión hay menos errores que se corrigen, las versiones definitivas son bastante inestables, al punto que instalarlas resultaba toda una odisea, quienes intentaron hacer una instalación gráfica con una tarjeta de video NVidia saben de lo que hablo, luego los informes interminables de errores que ahora parecen formar parte de la decoración del escritorio:


Actualmente estoy usando Xubuntu 13.04, pero en la versión anterior también aparecía constantemente el ícono en el escritorio y si se fijan bien no aparece el network-manager, esto es debido a que tuve que desinstalarlo para poder conectarme a la red (irónico, ¿verdad?)

Cuando Ubuntu adoptó Gnome 3 y Unity decidí cambiarme a Kubuntu, luego de varias experiencias que me llenaron de frustración, muchos widgets, efectos y detalles que no me gustaron cambié a Xubuntu. XFCE con todas las ventajas de Ubuntu, básicamente estuve saltando entre distintos escritorios, pero la misma distro.

Durante el primer año aproximadamente pude manejar la situación, pero ahora la razón para querer cambiar no era el gestor de escritorios, no eran los efectos, la razón para querer cambiar era la distro en sí misma. Siento que pierdo demasiado tiempo tratando de que algunas cosas funcionen, pero ¿para qué seguir hablando mal de una distro con la que pasé tan buenos momentos?

¿Qué busco? 


  • Estabilidad
  • Simplicidad
  • Velocidad
  • Repositorios con multitud de aplicaciones
  • Amistosa con los equipos de escritorio y portátiles
  • Buena documentación
  • Fácil de usar, instalar y configurar

Aparentemente la mayoría de las distribuciones encaja en estas características, pero he probado unas cuantas recientemente y mis opciones se reducen a dos:


Esta es la parte en la que algunos lectores se preguntarán "¿por qué no Linux X o Y Linux?" Porque de todas las que probé, estas dos son las que a mi criterio cumplen mejor las características que menciono anteriormente.

Es importante resaltar que esta elección es completamente personal ya que seré yo quien use la distribución, pero me agrada tener opciones, es lo mejor del mundo libre en el que aún vivimos. Para llegar a esta lista de dos distribuciones hice lo que comentan en todos los foros, listas, artículos, etc, "Prueba hasta que consigas una que te guste" y es mi recomendación para el lector que todavía esté en proceso de tomar una decisión.

Ambas tienen una comunidad muy amplia, los repositorios son muy generosos, estables hasta donde pude probar, la documentación es amplia y detallada, ambas funcionaron de manera brillante desde el comienzo (aunque instalé la beta de Fedora 19 no tuve problema alguno).

Una vez tome alguna decisión comentaré mi elección y las razones para ello, en caso de que esto pueda servir de ayuda.

jueves, 15 de marzo de 2012

Introducción a la computación paralela (parte 2: el problema)

Continuando con la serie de artículos asociados a la computación paralela vamos a plantear un problema bastante simple, pero que nos servirá para desarrollar y aplicar los conceptos de computación paralela sin enfocarnos demasiado en "el problema".

El problema consiste en encontrar las raíces de una función usando el método de bisección. Este método no es el más eficiente para la tarea y justamente por ello lo usaremos, así se podrá apreciar aún más la mejora al momento de paralelizar las tareas.

Antes de continuar le recomiendo al lector que visite algunas páginas para que entienda el algoritmo, que es bastante simple.

Ahora bien, como función usaremos el coseno ya que como todos saben es una función periódica que corta el eje X (como dije antes, la idea es que "el problema" sea simple), como es costumbre lo desarrollaré en Python:
import math

def f(x):
    return math.cos(x)
    
def biseccion(f, a, b, nIter, eps = 0.0001):
    fa = f(a)
    fb = f(b)
    m = (a + b) / 2.0
    fm = f(m)
    n = 0
    while n <= nIter and math.fabs(fm) > eps:
        if fa * fm < 0:
            b = m
            fb = fm
        else:
            a = m
            fa = fm
        m = (a + b) / 2.0
        fm = f(m)
        n += 1
    res = \
        {
            'r' : m,
            'fr': fm,
            'iteraciones': n,
            'criterio': n > nIter and \
                        'iteraciones' or 'tolerancia'
        }
    return res
    
if __name__ == '__main__':
    r = biseccion(f, 0, 4*math.pi, 100)
    print r

Como podrán notar no está escrito de la manera más eficiente posible (hablando en términos de Python), sin embargo me interesa que sea fácil de entender. La función bisección recibe como parámetros la función a la cual le buscará las raíces, el intervalo de búsqueda [a, b], la cantidad máxima de iteraciones y por último la tolerancia, error o epsilon, como prefieran llamarlo, así tendremos ambos criterios de convergencia en caso de que el otro falle. La función retorna un diccionario con los valores obtenidos (la raíz, el valor de la raíz en el punto, el número de iteraciones y el criterio de convergencia.

Ahora bien, compliquemos un poco más el problema para hacerlo más retador para el cumputador. Supongamos que deseamos encontrar todas las raíces en un intervalo muy amplio, por ejemplo [-1000, 1000], el método de bisección solo nos va a encontrar una raíz ¿cómo buscamos las otras? Para responder a esto usamos el método de búsqueda incremental.

El método de búsqueda incremental, como su nombre lo indica, consiste en buscar haciendo pequeños incrementos por lo que al final nos quedará una serie de conjuntos más pequeños en los cuales hacer la búsqueda, esto no garantiza todas las raíces, sin embargo se aproxima bastante bien (al menos para el ejemplo que deseamos desarrollar).

El método nos quedaría como sigue:
def incremental(inicio, fin, nIntervalos, nIter):
    inc = (fin - inicio) / nIntervalos
    res = []
    for i in range(nIntervalos):
        r = biseccion(f, inicio, inicio + inc, nIter)
        r.update({'a' : inicio, 'b' : inicio+inc})
        res.append(r)
        inicio += inc
    return res
Recibe como parámetros el inicio y el fin del intervalo, el número de trozos en el que se va a cortar dicho intervalo y el número de iteraciones que se hará en cada búsqueda de las raíces. Nos retorna una lista de diccionarios con los resultados de cada ejecución del método de bisección, para las pruebas iniciales recomiendo usar parámetros más conservadores, pero hice una prueba de la siguiente manera:

inicio = time.time()
    r = incremental(-10000.0, 10000.0, 100000, 1000)
    print "Tiempo transcurrido: ", time.time() - inicio, "s"

Aquí una captura de htop mientras se ejecuta la aplicación:


El computador en el que hice las pruebas es un Intel Core i3 con dos núcleos HT (por eso se ven 4) de los cuales únicamente se está usando uno a su máxima capacidad.

Se llevó aproximadamente 64.4822211266 s. Pues bien, ahora nos preguntamos: ¿hace falta ejecutarlo de manera secuencial? ¿no podría aprovechar de mejor manera varios núcleos?

La respuesta es un rotundo "sí", pero la respuesta al "¿cómo?" la veremos en el siguiente artículo.

Retomando el Blog

Luego de unos meses de estar desaparecido por estos lados por razones académicas y profesionales decidí retomar el Blog, continuar con la serie de artículos relacionados a la computación paralela y distribuida, además de otros artículos con temas mencionados en el primer post del blog.

Espero tener más tiempo ahora y al menos culminar los artículos que están en borrador...

Saludos a todos y feliz blogging ;)

viernes, 24 de junio de 2011

Introducción a la computación paralela (parte 1)

La idea es crear una serie de artículos en los que podamos cubrir algunos aspectos básicos y no tan básicos de la computación paralela para que el lector tenga un punto de partida en esta área tan fascinante y continúe investigando por su cuenta. En este primer artículo comenzaremos con los conceptos básicos que nos permitirán abordar de mejor manera los siguientes posts de esta serie.

Hoy en día se ha vuelto tan común tener PC's o portátiles con más de un procesador, núcleo o core (usen el que más les guste) por esto resulta importante explotar de manera adecuada esta ventaja, sobre todo con aplicaciones que consumen mucho tiempo de procesador como aplicar filtros y efectos complejos con Gimp, renderización de imáges, cálculos intensivos como simulaciones, programas que hagan uso de las técnicas de computación emergente, métodos de elementos finitos, juegos, etc.

Para aquellos que trabajamos en el área y sobre todo si nos gusta "jugar" con las técnicas de la computación emergente aprovechar todo el poder de cálculo que nos brindan los computadores resulta ideal. ¿Por qué uso Python y no C/C++ si lo que necesito es aumentar el rendimiento al máximo? Todas las librerías matemáticas que usa Python están escritas en C (numpy por ejemplo) así que básicamente lo que hacemos es un script que interactúa con las funciones hechas en C. Ahora bien, en este sentido podríamos usar Perl o el lenguaje de su preferencia, mi preferencia es Python =)

Comencemos con una breve introducción a la computación paralela, como podemos leer en la wikipedia:
La computación paralela es una técnica de programación en la que muchas instrucciones se ejecutan simultáneamente. Se basa en el principio de que los problemas grandes se pueden dividir en partes más pequeñas que pueden resolverse de forma concurrente ("en paralelo"). 
Tratemos de explicar este concepto con un ejemplo sencillo, deseamos realizar una encuesta a 1000 personas acerca de un asunto X. ¿Nos podríamos nosotros mismos a entrevistar a las 1000 personas? o ¿podríamos a un grupo de empleados a hacerlo? Durante el día cada empleado entrevistará una cuantas personas, cada uno de ellos con un grupo distinto. Acabamos de paralelizar el trabajo, además llamada "paralelismo de datos":
Paralelismo de datos es un paradigma de la programación concurrente que consiste en subdividir el conjunto de datos de entrada a un programa, de manera que a cada procesador le corresponda un subconjunto de esos datos. Cada procesador efectuará la misma secuencia de operaciones que los otros procesadores sobre su subconjunto de datos asignado. En resumen: se distribuyen los datos y se replican las tareas.
Otro ejemplo que nos servirá más adelante es el típico ejemplo de un banco. Supongamos que hablamos ahora de un banco en el que tenemos una cola de personas esperando ser atendidas y 4 taquillas en las que serán de ello (Quad Core o X4 jejeje). ¿Tendría sentido poner a todas las personas en la misma taquilla? o ¿pasaríamos a cada persona por una taquilla diferente a medida que se desocupen? Supongo que la respuesta más evidente para nosotros es atender a los clientes a medida que se desocupen las taquillas.

Entonces terminamos con una cola de "jobs" o trabajos por hacer y 4 "workers" o trabajadores que se encargarán de atender estas peticiones. Nuevamente tenemos la parelización de los trabajos:



A medida que las taquillas o workers (como se les conoce en la computación paralela) se van desocupando atienden a los clientes o jobs que tengan pendientes con estos.

También tenemos el paralelizmo de tareas:
Paralelismo de tareas es un paradigma de la programación concurrente que consiste en asignar distintas tareas a cada uno de los procesadores de un sistema de cómputo. En consecuencia, cada procesador efectuará su propia secuencia de operaciones.
Para entender este concepto vamos a imaginar una fábrica automotriz, en todo momento se están haciendo asientos, puertas, chasis, motores, etc. Al mismo tiempo se realizan tareas diferentes en distintas partes de la fábrica, incluso en fábricas diferentes (lo que en nuestro contexto sería computación distribuida).

Aquí nos topamos con otro concepto interesante, el de la computación distribuida, podemos tener poderosos clústers de cálculo capaces de realizar muchas más operaciones de las que podríamos en un único computador, puede estar compuesto desde un par de computadores personales hasta una gran cantidad de computadores especializados. La idea principal tras de esto es distribuir las tareas no solo entre los procesadores, si no también entre distintos computadores.

Como se podrá imaginar se puede hacer una combinacion de estos tres coceptos para obtener el mejor rendimiento en una aplicación que consuma una gran cantidad de recursos, por ejemplo podríamos tener un cluster en el que le asignamos una tarea a cada nodo (computador en nuestro cluster) y este a su vez paraleliza la tarea en varias partes.

En los siguientes artículos desarrollaremos algunos ejemplos de cada tipo de paralización que mencionamos en este post (hay más tipos, pero son los principales) incluso de computación distribuida.

lunes, 20 de junio de 2011

Instalación, configuración y personalizacion de EasyHotspot

Lo prometido es deuda, aquí está el artículo del hotspot que decidí usar para el proyecto que comenté en una entrada anterior, decidí usar EasyHotspot en vista de lo fácil que es de usar, instalar, configurar y personalizar.

La instalación es bastante sencilla como la de cualquier Ubuntu, el detalle que se debe tener en cuenta es el particionado en vista de que se trata de un servidor y no cualquier PC de escritorio (aunque si se desea, cosa que no recomiendo, se usa el particionado por defecto usando todo el disco). Para las pruebas iniciales usé una máquina virtual creada con Virtual Box, le asigné 4 Gb de disco duro, para un servidor de pruebas es más que suficiente.

En su página podemos encontrar los pasos para la instalación y configuración inicial, vamos a concentrarnos en los pasos siguientes a la instalación. En primer lugar y antes de comenzar a cargar la configuración perzonalizada actualizamos el código fuente de la interfaz web, para ello abrimos una cónsola, cambiamos el directorio y actualizamos de los repos:

cd /opt/local/web/easyhotspot
git pull
 Una vez hecho esto ya contamos con la última versión de la interfaz web, ahora debemos actualizar la base de datos (por eso la insistencia en no cargar ninguna configuración personalizada):

cd /opt/local/web/easyhotspot/install
Si listamos (ls -l) los archivos que se encuentran en la carpeta nos encontramos con tres (3) archivos .sql

database_with_sample.sqldatabase_schema_only.sql
easyhotspot_opensource_2010-10-21.sql
Particularmente usé easyhotspot_opensource_2010-10-21.sql, esto lo hacemos con:
$ mysql -u root -p easyhotspot_opensource < easyhotspot_opensource_2010-10-21.sql
La clave por defecto del MySQL es "easyhotspot", lo siguiente que hice fue cargar la configuración de la compañía a la que se le instalaría el hotspot en el archivo:

/opt/local/web/easyhotspot/htdocs/system/application/config/easyhotspot.php

En el podremos cambiar el nombre, dirección, separador de miles, decimales, entre otra cosas.

Para la mayoría esto, además de los pasos que se indican en la página, es suficiente para tener el servidor en funcionamiento, sin embargo tuve que cambair la pantalla de inicio de sesión para los clientes que por defecto se vé así:



El el foro de EasyHotspot podemos encontrar cómo cambiar la pantalla de inicio de sesión usando Php, pero como la solución no me funcionó decidí modificar directamente el cgi que está escrito en Perl  y se encuentra en:
/opt/local/web/easyhotspot/hotspot/hotspotlogin.cgi
Recomiendo hacer una copia de respaldo antes en caso de que algo no funcione bien, poder restaurarlo al estado inicial, hay que ser cuidadoso, una comilla mal puesta y no iniciará sesión adecuadamente.. El resultado fue algo como esto:


Obviamente taché los nombres de la compañía para evitar "detalles" legales. El cambio de clave Lo agregué yo, no forma parte de la solución y fue un requerimiento de los clientes. Es un script Php que actualiza las tablas en las que se encuentran los datos de registro de los clientes (postpaid_account y radcheck).

Si quieren más detalles acerca de la instalación o las modificaciones realizadas no duden en preguntar o comentar.

martes, 24 de mayo de 2011

Web 2.0 en las universidades

Como ya saben estoy estudiando Computación, estoy en los últimos semestres de la carrera y en una de las materias que estoy cursando se nos solicitó que usaramos las herramientas de la llamada "Web 2.0" para potenciar el aprendizaje, según podemos leer en Wikipedia:
El término Web 2.0 (2004–actualidad) está comúnmente asociado con aplicaciones web que facilitan el compartir información, la interoperabilidad, el diseño centrado en el usuario y la colaboración en la World Wide Web. Ejemplos de la Web 2.0 son las comunidades web, los servicios web, las aplicaciones Web, los servicios de red social, los servicios de alojamiento de videos, las wikis, blogs, mashups y folcsonomías.
 Lo cual me pareció una excelente idea en vista de que la carrera siempre se había centrado en aspectos muy técnicos relacionados con el área dejando de lado los complementos que podemos encontrar en la web actualmente, el problema: el enfoque usado.

En términos generales, y según entiendo yo, el término Web 2.0 está más relacionado con el hecho de la creación de comunidades, participación de los usuarios y/o mienbros dándole un enfoque novedoso a lo que estamos acostumbrado ver en la Web 1.0 (?).

Si partimos del supuesto que el postulado anterior es cierto, entonces el enfoque que se le está dando en la mencionada clase es erróneo, ¿por qué? se estará preguntando el lector sagaz; la respuesta: porque no hay participación, se está montando el contenido en una Wiki (www.wikispaces.com), presentaciones con Prezi (herramienta bastante agradable, aunque puede confundir un poco al principio). Se montan los arículos y ahí termina el proceso.

No hay participación del profesor, ni la posibilidad de comentar los artículos publicados por los compañeros ni siquiera de los semestres anteriores; aquí es donde me pregunto ¿cual es la gracia de todo esto si no hay participación? ¿corrección? ¿opinión?

Indudablemente estas inquietudes ya fueron manifestadas a la persona correspondiente, sin embargo espero que esta nota (bastante corta y poco técnica) pueda servir a quienes se encuentren en situaciones similares y quieran intentar un enfoque más adecuado al uso de herramientas de este estilo en las aulas de clases.