Nota del autor

Si la entrada que estás leyendo carece de imágenes, no se ve el vídeo que teóricamente lleva incrustado o el código fuente mostrado aparece sin formato, podéis conocer los motivos aquí. Poco a poco iré restableciendo la normalidad en el blog.
Este blog es un archivo de los artículos situados previamente en Lobosoft.es y ha dejado de ser actualizado. Las nuevas entradas pueden encontrarse en www.lobosoft.es. Un saludo,
Lobosoft.
Mostrando entradas con la etiqueta concurrente. Mostrar todas las entradas
Mostrando entradas con la etiqueta concurrente. Mostrar todas las entradas

martes, 23 de diciembre de 2008

Precaución, amigo conductor...

... tu enemigo es la velocidad... Vale, vale, ya me callo. Se vaya a liar a llover justo en Nochebuena y la liemos :) . El caso es que el título viene muy al caso para lo que quiero contaros hoy.


Aprovechaba un momento de solaz, días atrás, para echar un vistazo a un MSDN Magazine que me había pasado un amigo, y veía en el mismo cómo para la próxima versión de Visual Studio, que llegará a nuestras manos allá por 2010, trae “de serie” algunas de las herramientas y librerías con las que Microsoft nos está dejando jugar a través de Microsoft Research y sus proyectos beta. Entre otras, podíamos ver hace unos días y pocas entradas atrás, cómo Pex ya permite su integración con VS2008 y VS2010, y a esto podemos sumarle un sistema de depuración y pruebas en programación concurrente en el que, imagino, bastante tendrá que decirnos el equipo que está desarrollando CHESS, y que permite incluso depurar las aplicaciones sabiendo en cada momento sobre qué núcleo está corriendo cada hilo de las mismas, tener en cuenta la ocupación del mismo y comprobar todo tipo de condiciones de carrera para evitar que lleguen a producirse, pongamos por ejemplo, interbloqueos durante su ejecución.


A lo que iba (que ya comienzo a divagar) es que VS2010 dará un soporte importante a la programación multihilo, como venía diciendo, incorporando herramientas de interés para los desarrolladores de este tipo de sistemas. Y al hilo de esto (chiste malo :P), he de comentar que estuve echando un vistazo a la librería Accelerator, que Microsoft lanzó hace algo más de un año, aunque sigue en desarrollo y, obviamente, en beta. Su interés fundamental es permitir el desarrollo de aplicaciones en .NET que sean capaces de aprovechar el potencial de cálculo de las modernas GPUs (¿recordáis hace unos meses las noticias sobre ruptura de cifrados a través de fuerza utilizando estos dispositivos?). La verdad es que su uso es bastante simple, como todo lo que nos llega desde Redmond, y básicamente se trata de incluir una referencia a la librería de Accelerator en nuestro proyecto de Visual Studio y empezar a trabajar con ella. Eso sí, la tarjeta gráfica que usemos deberá ser compatible con DirectX9 y tener soporte para Pixel Shader 2.0, como mínimo. Esto es así porque las operaciones parelas con datos a código optimizado para la GPU y llamadas a la API correspondiente, permitiendo así una ejecución mucho más rápida de dichos cálculos. La librería Accelerator (en concreto, el espacio de nombres Microsoft.Research.DataParallelArrays) incorpora varios tipos de datos nuevos, como son el FloatParallelArray, IntParallelArray o BoolParallelArray, con operadores aritméticos sobrecargados para los mismos.


Obviamente, el uso más indicado para esta librería es, aparte de los cálculos relacionados con temas gráficos como el renderizado de imágenes u operaciones con objetos en 3D, el de llevar a cabo operaciones complejas que requieran cálculos matemáticos exhaustivos o muy precisos a una velocidad considerable. De este modo, la GPU puede constituir un soporte muy eficiente para la CPU, sea esta última multinúcleo o no.


Para finalizar, ya que trato el tema de la CPU, y volviendo al comienzo del artículo, me ha llamado la atención el publicado por Rodrigo Corral bajo el título ¡La broma ha terminado!, en el que reflexiona sobre el fin de la Ley de Moore, y cómo a partir de ahora los desarrolladores deberemos preocuparnos un poco más sobre cómo se ejecutan nuestras aplicaciones en el hardware disponible. De ahí que Microsoft y compañía se preocupen tanto de proporcionarnos ahora este tipo de herramientas, vengan incluidas en los frameworks, sean librerías externas, o lleguen de la mano de nuestro IDE preferido.

viernes, 31 de octubre de 2008

Me alegra que me haga esa pregunta

En la entrada de ayer introducía el uso de la clase Mutex para evitar el acceso concurrente a un determinado recurso (en ese caso concreto, a la ejecución simultánea dos o más veces de una misma aplicación). Lonifasiko pregunta, muy acertadamente, qué diferencia existe entre el uso de la palabra reservada lock y el propio Mutex. Lo cierto es que tanto la exclusión mutua de Mutex como el uso de monitores (lock implementa la clase Monitor) permiten el acceso exclusivo a recursos, pero cada uno tiene sus propias peculiaridades. Empecemos con lock.


En .NET, la palabra clave lock se puede usar para evitar que dos subprocesos accedan a un mismo objeto de forma simultánea. Esto se consigue pasándole a lock un objeto como argumento, seguido del bloque de código que deseamos ejecutar aisladamente en un subproceso (es decir, sin que interfieran otros subprocesos en su ejecución).



[csharp]
object miCandado = new object();
lock (miCandado)
{
// No molestar ;)
}
[/csharp]


El objeto en cuestión debe estar basado en un tipo de referencia y es usado para definir el ámbito del bloqueo, ya que estará dado por el alcance del objeto dentro de nuestra aplicación (si se ciñe a una determinada función o es mayor, en función de si existen referencias al objeto fuera de la misma). Microsoft, en su infinita sabiduría :P, desaconseja utilizar bloqueos en tipos public, o utilizando instancias de objetos que estén fuera del alcance de la aplicación, así como cadenas, ya que pueden producir interbloqueo entre procesos si otro código fuera del control de la aplicación utiliza ese mismo objeto para llevar a cabo un bloqueo. Resumiendo, que lo ideal es usar para el bloqueo objetos privados o protegidos, excepto las cadenas, que ni por esas: el CLR las “interna”, es decir, existe una única instancia de la cadena para toda la aplicación.


Como decía, la palabra reservada lock implementa la clase Monitor, facilitando su uso. Monitor es una clase del espacio de nombres System.Threading que contiene dos métodos, Enter y Exit. Al igual que con lock, en el método Enter debemos pasarle al monitor el objeto a usar para definir el ámbito del bloqueo. Cuando finalicemos el acceso exclusivo al recurso, debemos indicar su liberación mediante el método Exit. Así, nuestro pequeño ejemplo anterior quedaría como sigue:



[csharp]
object miCandado = new object();

Monitor.Enter(miCandado);
try
{
// No molestar ;)
}
finally
{
System.Threading.Monitor.Exit(miCandado);
}
[/csharp]


Todo esto está muy bien, resulta tan sencillo como el uso de Mutex, y de hecho es incluso más rápido y eficiente. ¿Entonces, por qué usar Mutex? Bien, la diferencia (jejeje, me he hecho de rogar, pero aquí está por fin) está en que lock permite la exclusión mutua entre subprocesos hijos de un mismo proceso, pero no entre subprocesos de distintos procesos. Es decir, podemos excluir el acceso a un recurso dentro de la misma aplicación, pero no entre aplicaciones (procesos) distintos. Por esto, ya que lo que ayer deseábamos era evitar la ejecución simultánea de dos aplicaciones (que en ese caso podrían ser la misma o no, basándonos simplemente en que utilizasen el mismo nombre para el mutex creado), me basé en el uso de la clase Mutex.


Si os interesa el tema de la programación concurrente os recomiendo el recurso Threading in C#, de Joseph Albahari (precisamente en la parte 2 profundiza en las diferencias entre lock, Mutex y la tercera parte en discordia, que de momento le dejaremos a él: el uso de semáforos).