domingo, 30 de abril de 2017

Teaching the SIMD Execution Model

Hoy hablaré de un artículo escrito por el profesor Ariel Ortiz sobre la enseñanza del modelo SIMD (Single Instruction, Multiple Data) de programación en ensamblador.

Como es tradición, comenzaré con la canción de esta entrada, y dado que será la última entrada del curso (no necesariamente del blog), he elegido una canción especial, la canción de la entrada será "Goodbye" del grupo Coreano 2NE1, espero les guste.


Aprender lenguaje ensamblador es difícil, aprender lenguaje ensamblador utilizando instrucciones para desarrollar aplicaciones concurrentes es aún más díficil, programar en lenguaje ensamblador requiere conocer a muy bajo nivel las especificaciones del procesador, además de conocer instrucciones crípticas que te hacen pensar que resolver bugs para programas de COBOL no sea tan malo.

Sin embargo, considero que tener una idea general de cómo programar en ensamblador aporta un gran área de conocimiento a un desarrollador, aunque quizá no lo utilice en la práctica, conocer lo que hay detrás de las llamadas de otros lenguajes de más alto nivel puede ayudar al desarrollador a entender los detalles de implementación de más bajo nivel, lo cuál lo ayuda a entender mucho mejor un sistema, incluso ayudando al desarrollador a tomar mejores decisiones de arquitectura (puede incluso evitar que un desarrollador decida utilizar un lenguaje monstruoso, como Lua).

Los nuevos procesadores soportan un set de instrucciones que permiten procesar en paralelo cierta información, por lo que un programa desarrollado directamente en lenguaje ensamblador que utilice instrucciones de procesamiento concurrente puede acelerar una aplicación de una forma que con cualquier otro lenguaje, a menos que se utilice un compilador de alto rendimiento se podría obtener, el tradeoff es que el desarrollador debe comprender perfectamente cómo se debe procesar la información a un nivel muy bajo para evitar problemas que son practicamente imposibles de debuggear.

Creo que aprender a desarrollar en lenguaje ensamblador, aunque sean aplicaciones relativamente sencillas, brinda una forma de pensar muy poderosa al desarrollador, ya que lo ayuda a conocer a nivel extremadamente bajo como se mueve, procesa y almacena la información en el procesador.

Wololo.

sábado, 29 de abril de 2017

¿Sueñan los Androides con Ovejas Eléctricas?

Para el blog de hoy hablaré sobre un libro que leímos en el curso de programación multinúcleo llamado "¿Sueñan los Androides con Ovejas Eléctricas?" escrito por Philip K. Dick en el año 1968.

Como es costumbre, empezaré con la canción para esta entrada, esta vez será "2 Cool For School" de The Androids, espero les guste.



Sueñan los Androides con Ovejas Eléctricas es una novela futurista que plantea un mundo devastado por una guerra nuclear, la novela comienza con una definición muy clara entre los humanos y los androides, cuya única diferencia parece ser la falta de empatía, sin embargo, conforme va avanzando la trama del libro la línea entre androides y humanos se torna borrosa, ya que se presenta a una humanidad en decadencia, en donde los mismos humanos se muestran desconfiados y despiadados.

A medida que la trama avanza, el libro obliga al lector a preguntarse las presupuestas diferencias entre los humanos y los androides, al presentar la posibilidad de que exista amistad o amor entre ambos, el lector se enfrenta a ciertas preguntas filósoficas como si la falta de empatía de los androides se deba a su situación como esclavos en Marte, así cómo la condición humana de los habitantes de la tierra, que por las circunstancias tan precarias de la vida en la tierra, devastada por la guerra nuclear, han perdido su humanidad.

Se puede preveer las cuestiones filosóficas que el libro maneja desde el título del libro "¿Sueñan los Androides con Ovejas Eléctricas?".

El libro utiliza los animales como un elemento importante para secundar la hipótesis inicial, ya que una de las motivaciones principales del protagonista es encontrar un animal real, ya que los animales han sido reemplazados por androides, que son exactamente iguales a los animales "reales", a diferencia de que éstos deben repararse. Creo que este elemento concede a la gran narrativa de la novela, ya que permite al lector empatizar por las motivaciones personales del protagonista.

Al final de la obra Rick Deckard encuentra una rana, que al llevar a su casa es analizada por la esposa del protagonista, Iran Deckard, al analizar la rana Iran descubre que en realidad la rana es un androide, Rick después concluye que a pesar de que no sea una rana "real", no debe considerarse como una cosa no viviente. Lo cual me parece una analogía poderosa para narrar una conclusión profundamente metafórica, ya que, el lector en un principio puede sentir una sensación de vació por descubrir que a pesar de todo Rick no cumplirá su sueño de tener un animal real, sin embargo, considero que el final explica perfectamente la hipótesis que el autor quiso plantear a través de todo el libro, el proceso en el que el protagonista acepta finalmente que los androides son también una forma de vida. En parte por su experiencia con otros androides a través del libro, pero secundado por la analogía de los animales, que desde el principio del libro se plantearon como una de las motivaciones principales del protagonista, ya sea que Rick haya aceptado a los androides como una forma de vida por su experiencia a través del libro o por simple desesperación por cumplir sus sueños. El lector se queda con la pregunta fundamental "En un mundo futurista como el que propone Philip K. Dick la tecnología convirtió a los robots en seres humanoides, o los humanos, ya sea por avances tecnológicos o por los estragos de la guerra ¿se convirtieron en androides?".

Sin duda algunos de los grandes juegos recientes sobre distopías han utilizado la novela como referencia, así que dejaré un par de trailers al final de esta entrada por si quieren revisarlos.

Wololo.








lunes, 24 de abril de 2017

The State of Parallel Programming

En esta entrada escribiré sobre un artículo llamado "The State of Parallel Programming" por UBM TechWeb.

Como es cosumbre, empezaré con la canción de esta entrada, será "No Parallels" por Hands Like Houses.


En mi experiencia como programador, las race conditions y problemas de memoria son similar a los problemas de contaminación de vivir en la Ciudad de México, pasé toda mi tierna infancia sin conocer los riesgos de salud que la contaminación en la Ciudad de México, era feliz, hasta que un día, probablemente durante la pubertad, leí acerca de las contigencias ambientales y como la ciudad es básicamente una enorme cámara de smog, lentamente matándonos.

Probablemente haya exagerado un poco en el párrafo anterior, pero lo necesitaba para argumentar lo siguiente:
Ya que existen varias herramientas que facilitan el desarrollo de aplicaciones multinúcleo, pasé mis primeros días como desarrollador de aplicaciones móviles feliz en la ignorancia de dichos problemas, no me tenía que preocupar por nada ¿consumir servicios web? utilizaré esta función que dice que solo recibe la URL y response con un JSON, en la siguiente línea mandaré los datos a mi tabla con unos 1,000 registros ¿Qué es lo peor que puede pasar? Es más, de una vez aprovecharé para agregar esta librería que dice que maneja efectos visuales cada que una tabla es modificada, se verá bien.

Y por mucho tiempo me salí con la mía, hasta que un día sucedío, mi aplicación crasheaba en momentos irregulares, a veces sin que el usuario clickeara nada, a veces en medio de consumir el servicio web. Probablemente pasé un par de días buscando resolverlo, mejor dicho, pasé los primeros días en negación, seguro es un bug de una de las librerías, no fue hasta que perdí toda la esperanza que investigué y encontré la mismísima caja de Pandora, descubrí sobre el manejo de hilos en aplicaciones móviles, y desde entonces mi vida cambió, pero no forzosamente para bien.

Resultó que todas las librerías que utilizaba requerían llamarse de formas especiales en momentos especiales para poder sincronizarse y no causar crashes random por tratar de leer o modificar un dato que quizá ya no estaba ahí, después no supe nada, solo podía ver un gran hongo radioactivo que representaba todo lo que había estado haciendo mal hasta ese momento explotando en mi cara.

En resumen, descubrí que el hilo central en aplicaciones únicamente es para UI, ¿Servicios web? crea un hiló y ejecútalo de forma asíncrona, cuando termine (si termina) implementa un patrón de observador para que el servicio notifique al UI para que se actualice.

Desde aquel momento mi enfoque al programar cambió drasticamente, paso al menos una sexta parte del tiempo total en que desarrollo aplicaciones revisando que tenga los métodos de sincronización adecuados y otro tercio revisando que no tenga problemas de memoria, pero esa es otra historia.

A eso debo sumar el tiempo que paso leyendo las implementaciones específicas de cada librería que uso, justo hoy tuve un problema con una aplicación legacy que alguien más programó en la empresa que trabajo hace cinco años, alguien que en ese momento aún vivía en su tierna infancia sin race conditions, en resumen, implementó todos los servicios con una función web no asíncrona (y confiaba que no tardara mucho o muriera, porque por supuesto, bloqueaba el hilo central de la aplicación, por cinco bellos años la aplicación funcionó sin muchos problemas, hasta que en la última actualización de sistema operativo Apple decidió que ya no tendría funciones web que soportaran dicha monstruosidad, y en su defecto dejó una función que se llama igual pero a bajo nivel sí es asíncrona y pone un lock en el hilo central para que cosas como la que hizo aquel programador no se rompieran por completo, el problema es que además de ello implementó un mecanismo que crashea la aplicación automáticamente al detectar que un hilo no central trata de modificar el UI, por lo que el código no asíncrono que en algún momento sí se ejecutaba en el hilo central al terminar la función, ahora no lo hacía (aunque el hilo central tuviera un lock),  y por lo tanto, crasheaba la aplicación cada que se consumía un servicio web, todo esto fue de la noche a la mañana. Fue una madrugada divertida.

La razón por la que he decidido contar esta anécdota es porque las gráficas que muestra el artículo plantean un paradigma espantoso para los siguientes años, únicamente 28% de los programadores encuestados no utiliza una herramienta de performance tuning, y aún así, 74% de los programadores no usa o no sabe que herramienta usa para detectar errores de threading, lo cual es curioso, porque al enfocarse en performance sin preocuparse por errores de sincronización muchos desarrolladores pueden caer en el patrón de mandar todo a diferentes hilos en busca de mejorar el performance de su aplicación sin preocuparse por los mecanismos que usara para que la los módulos "paralelizados" sean thread safe, lo peor de todo es que una aplicación que utiliza componentes que no son thread safe puede funcionar por meses, quizá años, hasta que un día algo sucede mal, y todo explota, y dado que el scheduling de los hilos es relativamente aleatorio debuggear aplicaciones con problemas de la sincronización es una de las cosas que te hacen considerar que quizá hubieras sido más feliz cultivando maíz en Matehuala, ¡O HASTA PROGRAMANDO EN LUA!

Las demás gráficas comprueban mi hipótesis, 33% de los programadores encuestados dijeron que considera que se necesita desarrollar más tecnología que determine las secciones de mayor beneficio por paralelizar, pero sólo 21% considera que las tecnologías paralelas deberían evitar el uso incorrecto de paralelización, y solo 8% considera que se necesitan módulos para encontrar defectos, la cosa se pone peor, únicamente un 7% considera que se necesitan librerías que sean thread_safe. Estamos programando nuestra propia tumba. 

Es indispensable entender el concepto de programación concurrente, porque en general, implementar una aplicación concurrente mal programada es peor, por mucho, que implementar una aplicación no concurrente correctamente.

Eso es todo para la entrada de hoy.
Wololo.

MapReduce: Simplified Data Processing on Large Clusters

Para la entrada de hoy hablaré sobre un paradigma desarrollado por Google para manejar datos de forma concurrente descrito en el artículo MapReduce: Simplified Data Processing on Large Clusters, por Jeffrey Dean y Sanjay Ghemawat.

La canción de esta entrada será "Maps" de Maroon 5, espero les guste.



MapReduce es un modelo de programación que facilita el procesamiento de múltiples datos de forma paralela, la forma en la que este modelo funciona es facilitando un modulo MapReduce que recibe una función Map a aplicar a un set de datos, la funcionalidad de Map es recibir llaves y valores de un set de datos y generar una lista con las llaves y los valores posteriormente se utiliza la función Reduce, que toma la lista y la procesa de forma que devuelva una lista de valores, lo interesante del modelo es que abstrae los detalles de implementación de los módulos encargados de la sincronización de las funciones entre múltiples hilos de ejecución, permitiendo al desarrollador enfocarse en la transformación que desea realizar en los datos obtenidos.


La funcionalidad más atractiva de MapReduce es el hecho de poder distribuir una tarea entre múltiples unidades de procesamiento sin preocuparse por balanceo de cargas o sincronización, el modelo ha sido tan efectivo que ha sido implementado en prácticamente cualquier lenguaje de programación decente (¡incluso ha sido implementado en Lua!).

El artículo me pareció interesante, sin embargo, me hubiera gustado que tuviera más ejemplos de código para entender de una forma menos abstracta cómo está utilizando Google el modelo de MapReduce.

Wololo.


Indie Game: The Movie

En esta entrada hablaré de una película que vimos en clase llamada "Indie Game: The Movie" del año 2012, que relata la historia de varios desarrolladores de algunos juegos indie.

La canción de este blog es un cover de una de mis canciones favoritas de mi juego favorito "Song of Time and Song of Storms" cover por Taylor Davis.



En los últimos años la industria de los juegos indie ha crecido de forma exponencial, esto se debe en gran medida a que se han creado plataformas que han facilitado su distribución como Steam, Itch.io y Humble Store, pero además de ello el crecimiento de la industria de juegos independientes se debe a muchos otros factores que van desde tecnológicos hasta socio-culturales.

Desde el punto de vista tecnológico la creación de engines de juegos que cuentan con toda la funcionalidad básica ha contribuído a que sea más fácil para un desarrollador independiente crear un juego, basta una tarde para descargar de forma gratuita engines como Unreal o Unity, ambos con tutoriales, videos, música y assets gratuitos suficientes para desarrollar al menos un prototipo en cuestión de un par de horas, hace años ni siquiera existían engines similares, por lo que un equipo debía desarrollar desde cero el engine o comprarlo por miles de dólares. Otro aspecto tecnológico es la capacidad de procesamiento de las computadoras, que al ser mucho mayor han permitido que un estudio de desarrollo publique juegos que no están completamente optimizados y aún así ser 100% jugables (sí, estoy hablando de ti, Minecraft).

Por último, el factor socio-cultural, ha medida que la tecnología ha avanzado, muchas compañias que desarrollan juegos AAA se han enfocado en su mayor parte ha desarrollar juegos que sean visualmente atractivos aunque carezcan de mecánicas innovadoras en términos de jugabilidad en muchos casos reutilizando el mismo engine una y otra vez (sí, estoy hablando de ti, The Sims, Fifa, básicamente cualquier juego desarrollado por EA, la mayoría de los juegos de Ubisoft, Halo, Call of Duty, entre muchos otros). Por ello no significa que los juegos sean malos, sino que el hecho de pertenecer a una gama de juegos de tan alto presupuesto hace que el estudio que los desarrolla tenga que tomar decisiones que "aseguren" la rentabilidad del juego, por lo que su capacidad para tomar riesgos es limitada.

Por otro lado, los juegos independientes, al contar con presupuestos mucho menores, dependen casi exclusivamente de dichos riesgos, en su mayor parte, enfocándose a la historia o el gameplay, que son elementos más económicos que modelar con hiperrealismo cada asset del juego, algunos ejemplos son juegos que salen en la película, como Super Meat Boy, Fez o Braid, otros como Undertale, Stardew Valley, Hotline Miami, Stanley Parable, todos han sido juegos desarrollados con un presupuesto limitado, que han apostado su éxito a tomar riesgos que los diferencíen de otros títulos.

La película es una excelente ventana para ver el mundo del desarrollo independiente de videojuegos, los retos que los desarrolladores enfrentan y los resultados que obtuvieron aquellos que tuvieron una mezcla de suerte, visión y pasión por su producto.

Wololo.

Teaching Concurrency with Erlang

En el blog de hoy hablaré sobre el artículo "Teaching Concurrency with Erlang" escrito por el profesor Ariel Ortiz en el 2011.

Como es costumbre, empezaré con la canción para esta entrada, esta vez será "Flamingo" por La Vida Boheme, espero les guste.


El artículo habla principalmente de los retos que implica enseñar programación concurrente, creo que esto se debe a varias razones, en primera, a pesar de que los lenguajes funcionales facilitan la programación concurrente, implican una curva de aprendizaje que considero incluso mayor a aprender programación orientada a objetos, en mi experiencia, que aprendí priemero programación procedural, después programación orientada a objetos y por último programación funcional esto se debe a que a pesar de que la programación orientada a objetos implica un paradigma distinto, de cierta forma estamos acostumbrados a visualizar las cosas a nuestro alrededor como objetos que realizan funciones (el clásico diagrama de Transporte -> Automóvil - Aviones con el que uno aprende herencia en programación orientada a objetos), sin embargo, la programación funcional es complicada, el hecho de que no existan ciclos y las variables sean inmutables hace complicado entender cómo se pasa la información dentro de la aplicación, además de ello, cuando uno aprende un lenguaje funcional para desarrollar aplicaciones concurrentes esto introduce el problema de que además uno debe imaginar cómo se pasa la información en la aplicación en distintos tiempos, por lo que son varios conceptos distintos a lo que uno se ha acostumbrado.

Por supuesto que si uno ha trabajo con locks una vez que supera la curva de aprendizaje de lenguajes funcionales encuentra el porqué son tan buenos para aplicaciones concurrentes, en mi caso específico, con Erlang fue extremadamente fácil, ya que había llevado un curso de programación con Clojure, el cuál sufrí porque además de todos los conceptos nuevos que comenté previamente Clojure introduce el problema de entender la sintaxis de Lisp, lo cuál es un tema para otro blog. o quizá para mi terapeuta, porque en verdad fue algo traumático.

Erlang me parece un lenguaje perfecto para enseñar concurrencia, ya que el hecho de que los programas se dividen en procesos facilita entender el paso de información entre dichos procesos, mientras que los ciclos se resuelven si uno tiene cierta experiencia con funciones recursivas.

Durante el curso he desarrollado aplicaciones concurrentes en C, Java, Javascript, Erlang y Elixir, hasta ahora el lenguaje que me ha parecido más sencillo es Elixir, sin embargo eso se debe a que ya tenía cierta experiencia con Erlang.

Wololo.

Joe Armstrong on Erlang

Para el blog de hoy hablaré sobre el podcast titulado "Joe Armstrong on Erlang" producido por Software Engineering Radio en el 2008, por si no lo han escuchado, les dejaré una liga aquí.

Antes de empezar, la canción de este blog será "Dramamine" por Modest Mouse, espero les guste.


El invitado del podcast es Joe Armstrong, desarrollador del lenguaje de programación Erlang, desarrollado por Ericsson.

En el podcast habla sobre el desarrollo de Erlang, que fue desarrollado por la empresa Ericsson, el lenguaje nace de la necesidad de la empresa de telecomunicaciones de desarrollar código que sea tolerante a fallas, que tenga la capacidad de manejar múltiples procesos simultáneamente de forma segura y con la posibilidad de hacer cambios en el código sin reiniciar el programa, algo conocido como hot code loading, que considero como una de las funcionalidades más interesantes de Erlang, ya que el código en Erlang se divide por módulos, la máquina virtual de Erlang permite cargar dos módulos de un programa de forma simultánea, uno viejo y uno nuevo, con la posibilidad de cambiar al código nuevo sin reiniciar el programa.

Joe Armstrong habla en el podcast de los inicios de Erlang, desarrollado como un experimento en Prolog inicialmente, los cambios que se tuvieron que hacer para que Ericsson utilizara Erlang en términos de eficiencia, finalmente habla de algunos conceptos de Erlang que no son tan comunes en lenguajes de programación mainstream, como pattern matching, que permite definir comportamientos específicos según los parámetros que recibe una función.

Otro aspecto que me pareció interesante es el enfoque de Joe Armstrong sobre Erlang en términos de tolerancia a fallos, ya que comenta que en otros lenguajes de programación se hace énfasis en programación defensiva para prevenir errores, mientras Erlang tiene un enfoque de "fail fast" que permite a los procesos fallar sin detener la ejecución del programa, en cambio el hecho de que se permita a los procesos fallar permite que el supervisor de procesos inicie un proceso nuevo, este enfoque flexible me parece que permite al desarrollador enfocarse en la funcionalidad de su aplicación sin utilizar mucho tiempo en prevenir errores (sí, estoy hablando de Java).

Erlang me parece un lenguaje excelente para aprender programación funcional, me parece que su sintáxis es mucho más fácil de entender que en un dialecto de Lisp (como Clojure), al menos para principiantes en el paradigma de programación funcional.

Eso es todo por este blog, nos leemos pronto.
Wololo.