<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7418782953908644596</id><updated>2011-11-27T16:23:57.159-08:00</updated><category term='puntero a void'/><category term='cuda'/><category term='punteros'/><category term='busqueda de soluciones'/><category term='TDA'/><category term='cores'/><category term='programacion'/><category term='algoritmos'/><category term='fugas de memoria'/><category term='generico'/><category term='bioinspiracion'/><category term='memory leaks'/><category term='nvidia'/><category term='c'/><title type='text'>elarmarioinformatico</title><subtitle type='html'>Descubre aspectos avanzados e interesantes sobre algoritmos y algunos lenguajes de programación.
Se intentará que amplies tus conocimientos a nivel general, introduciendo algo de ingeniería, gestión de proyectos, análisis...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://elarmarioinformatico.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://elarmarioinformatico.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>cualquiera</name><uri>http://www.blogger.com/profile/06985416258894591114</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7418782953908644596.post-6350780893748649324</id><published>2010-04-05T00:32:00.000-07:00</published><updated>2010-04-10T08:50:24.190-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programacion'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><category scheme='http://www.blogger.com/atom/ns#' term='nvidia'/><category scheme='http://www.blogger.com/atom/ns#' term='cuda'/><title type='text'>CUDA: modelo de programación</title><content type='html'>En los últimos años se está explotando el potencial de las tarjetas  gráficas para otros propósitos, a parte del que le hemos dado hasta el  momento.&lt;br /&gt;Estamos hablando de un procesador capaz de mover millones de  polígonos y realizar operaciones sobre matrices enormes en un tiempo  mínimo, ¿porqué limitarnos a usarlo únicamente con ese propósito?&lt;br /&gt;Esto  se ha denominado como GPUGP (Graphic Process Unit General Purpose) y  existen diversas extensiones y lenguajes de programación que explotan  algunas arquitecturas de algunas GPUs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;CUDA&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En Noviembre de 2006, NVIDIA crea CUDA (Compute  Unified Device Architecture), una arquitectura de procesamiento paralelo  de propósito general, con un nuevo modelo de programación paralela.&lt;br /&gt;Con  esta extesión se puede obtener un código escalable a 100s cores y a  1000s hilos paralelos, independientemente de cuál sea la arquitectura  del procesador CUDA.&lt;br /&gt;Empezó como una pequeña extensión de C, pero ya  es soportada por OpenCL, Fortran...&lt;br /&gt;Antes de comenzar, vamos a ver  una serie de equivalencias y aspectos fundamentales inherentes&lt;br /&gt;del  comportamiento de CUDA:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Device  &lt;/span&gt;= GPU&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Host &lt;/span&gt;=  CPU&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Kernel &lt;/span&gt;= Función  llamada desde el Host que se ejecuta en Device&lt;/li&gt;&lt;li&gt;1 &lt;span style="font-style: italic;"&gt;CUDA Kernel&lt;/span&gt; se ejecuta mediante un &lt;span style="font-style: italic;"&gt;array de Threads.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Todos los  Threads ejecutan el mismo código.&lt;/li&gt;&lt;li&gt;Cada Thread tiene un ID que se  usa para direccionar la memoria y tomar las decisiones de control.&lt;/li&gt;&lt;li&gt;Unidad   básica de operación es el Thread.&lt;/li&gt;&lt;li&gt;Los Threads están organizados  en bloques de Threads. &lt;span style="color: rgb(51, 204, 0);"&gt;(Blocks)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Los   bloques están organizados en mallas de bloques. &lt;span style="color: rgb(51, 204, 0);"&gt;(Grids).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Un &lt;span style="font-style: italic;"&gt;Grid &lt;/span&gt;solo puede ejecutar un &lt;span style="font-style: italic;"&gt;Kernel&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PXahzV_MA9Y/S7mWCWBJK3I/AAAAAAAAABc/3ssEoGDgMmI/s1600/Dibujo.JPG"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 250px; height: 320px;" src="http://2.bp.blogspot.com/_PXahzV_MA9Y/S7mWCWBJK3I/AAAAAAAAABc/3ssEoGDgMmI/s320/Dibujo.JPG" alt="" id="BLOGGER_PHOTO_ID_5456557390550346610" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Los Threads van identificados mediante &lt;span style="font-style: italic; color: rgb(51, 204, 0);"&gt;threadIdx&lt;/span&gt;, que es un array de&lt;br /&gt;elementos 3D ( tiene 3 componentes, &lt;span style="font-style: italic;"&gt;x, y&lt;/span&gt; y &lt;span style="font-style: italic;"&gt;z&lt;/span&gt;) .&lt;br /&gt;Cada Thread puede venir identificado por un índice, es decir, puede tener 1, 2 ó 3 dimensiones, que dependará de cómo vayamos a explotar el paralelismo y del uso del &lt;span style="font-style: italic;"&gt;grid&lt;/span&gt;.&lt;br /&gt;Los Threads de un &lt;span style="font-style: italic;"&gt;bloque &lt;/span&gt;pueden cooperar entre sí mediante el uso de memoria compartida dentro del &lt;span style="font-style: italic;"&gt;bloque &lt;/span&gt;y sincronizando su ejecución para coordinar los accesos a memoria, para lo que usaremos el identificador mencionado anteriormente.&lt;br /&gt;Los &lt;span style="font-style: italic;"&gt;grids &lt;/span&gt;pueden ser de 1 o 2 dimensiones, luego cada bloque dentro de un &lt;span style="font-style: italic;"&gt;grid &lt;/span&gt;puede ser direccionado por un índice de 1 o 2 dimensiones mediante &lt;span style="font-style: italic; color: rgb(51, 204, 0);"&gt;blockIdx&lt;/span&gt;.&lt;br /&gt;Asimismo, la dimensión del bloque también se puede obtener desde dentro del kernel mediante &lt;span style="color: rgb(51, 204, 0); font-style: italic;"&gt;blockDim&lt;/span&gt;.&lt;br /&gt;Los&lt;span style="font-style: italic;"&gt; Cuda Threads&lt;/span&gt; pueden acceder a los datos de múltiples espacios de memoria durante su ejecución, ya que:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Cada Thread posee su propia memoria local.&lt;/li&gt;&lt;li&gt;Cada &lt;span style="font-style: italic;"&gt;bloque&lt;/span&gt; su propia memoria compartida por todos los threads del &lt;span style="font-style: italic;"&gt;bloque &lt;/span&gt;y con el mismo tiempo de vida que los Threads que lo componen.&lt;/li&gt;&lt;/ul&gt;Todos los Trheads tienen acceso a la memoria global.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PXahzV_MA9Y/S7mYfjmk2uI/AAAAAAAAABk/51pzNs0Jxc4/s1600/Dibujo.JPG"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 261px; height: 320px;" src="http://2.bp.blogspot.com/_PXahzV_MA9Y/S7mYfjmk2uI/AAAAAAAAABk/51pzNs0Jxc4/s320/Dibujo.JPG" alt="" id="BLOGGER_PHOTO_ID_5456560091436473058" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;El &lt;span style="font-weight: bold; font-style: italic;"&gt;modelo de programación&lt;/span&gt; de &lt;span style="font-style: italic;"&gt;CUDA &lt;/span&gt;asume que los &lt;span style="font-style: italic;"&gt;CUDA threads&lt;/span&gt; se ejecutan en un &lt;span style="font-style: italic;"&gt;device&lt;/span&gt; que actúa como coprocesador de un &lt;span style="font-style: italic;"&gt;host &lt;/span&gt;que ejecuta un programa, proporcionando instrucciones para reservar, liberar, copiar memoria en la  memoria del &lt;span style="font-style: italic;"&gt;device&lt;/span&gt;, así como  transferir datos entre el host y el device.&lt;br /&gt;Este modelo asume que &lt;span style="font-style: italic;"&gt;host &lt;/span&gt;y &lt;span style="font-style: italic;"&gt;device &lt;/span&gt;poseen su propia DRAM, host memory y device memory.&lt;br /&gt;CUDA.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;Kernel&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7mbuxR2ZVI/AAAAAAAAABs/CXa7miFsVEU/s1600/Dibujo.JPG"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 233px;" src="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7mbuxR2ZVI/AAAAAAAAABs/CXa7miFsVEU/s320/Dibujo.JPG" alt="" id="BLOGGER_PHOTO_ID_5456563651340559698" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;Escalabilidad y sincronización&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PXahzV_MA9Y/S7mcvDc3rjI/AAAAAAAAAB0/PahwAIRNycU/s1600/Dibujo.JPG"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 224px;" src="http://3.bp.blogspot.com/_PXahzV_MA9Y/S7mcvDc3rjI/AAAAAAAAAB0/PahwAIRNycU/s320/Dibujo.JPG" alt="" id="BLOGGER_PHOTO_ID_5456564755730247218" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;El tamaño del &lt;span style="font-style: italic;"&gt;bloque &lt;/span&gt;es elegido aparentemente de forma “arbitraria”, y el grid es creado con suficientes &lt;span style="font-style: italic;"&gt;bloques&lt;/span&gt; para tener un &lt;span style="font-style: italic;"&gt;Thread &lt;/span&gt;por un elemento de la matriz.&lt;br /&gt;Todos los Threads de un &lt;span style="font-style: italic;"&gt;bloque &lt;/span&gt;se ejecutan dentro del mismo &lt;span style="font-style: italic;"&gt;core&lt;/span&gt;. El número de threads por &lt;span style="font-style: italic;"&gt;bloque&lt;/span&gt; está limitado por los recursos de memoria del &lt;span style="font-style: italic;"&gt;core&lt;/span&gt;:&lt;br /&gt;En la misma GPU, actualmente(?) un bloque puede contener 512 threads.&lt;br /&gt;El tamaño de los datos suele ser más grande que el de los &lt;span style="font-style: italic;"&gt;bloques&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Independencia de ejecución entre bloques: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Se busca que sea indiferente el orden en el que se ejecutan, y si se ejecutan en paralelo o en serie.&lt;br /&gt;Si no, usar &lt;span style="font-style: italic;"&gt;__syncthreads()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Concluyendo, los &lt;span style="font-style: italic;"&gt;bloques&lt;/span&gt; son necearios para permitir la escalabilidad a diferentes números de cores.&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;Accesos a Memoria:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CUDA asume que device y host tienen su propia memoria. En principio, device trabaja con la host memory. Para que trabaje con su propia memoria, CUDA proporciona, entre otros:&lt;br /&gt;&lt;ul style="font-style: italic;"&gt;&lt;li&gt;cudaMalloc(void **, size_t);&lt;/li&gt;&lt;li&gt;cudaMemcpy(void *,void *,&lt;/li&gt;&lt;li&gt;size_t,cudaMemcpyHostToDevice|&lt;/li&gt;&lt;li&gt;cudaMemcpyDeviceToHost);&lt;/li&gt;&lt;li&gt;cudaFree(void *);&lt;/li&gt;&lt;/ul&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;Compilación&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PXahzV_MA9Y/S7mfe8xZcJI/AAAAAAAAAB8/yN7xc62tSfQ/s1600/Dibujo.JPG"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 220px;" src="http://4.bp.blogspot.com/_PXahzV_MA9Y/S7mfe8xZcJI/AAAAAAAAAB8/yN7xc62tSfQ/s320/Dibujo.JPG" alt="" id="BLOGGER_PHOTO_ID_5456567777594273938" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;Apéndice&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Interoperatividad con Directx y OpenGL.&lt;/li&gt;&lt;li&gt;Versión 2.3.1 (26/08/2009)&lt;/li&gt;&lt;li&gt;Arquitectura actual(?): nvidia FERMI: 512 cuda cores.&lt;/li&gt;&lt;li&gt;228 universidades enseñan cuda actualmente. (4 de ellas Españolas&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7418782953908644596-6350780893748649324?l=elarmarioinformatico.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://elarmarioinformatico.blogspot.com/feeds/6350780893748649324/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://elarmarioinformatico.blogspot.com/2010/04/cuda-modelo-de-pgramacion.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default/6350780893748649324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default/6350780893748649324'/><link rel='alternate' type='text/html' href='http://elarmarioinformatico.blogspot.com/2010/04/cuda-modelo-de-pgramacion.html' title='CUDA: modelo de programación'/><author><name>cualquiera</name><uri>http://www.blogger.com/profile/06985416258894591114</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PXahzV_MA9Y/S7mWCWBJK3I/AAAAAAAAABc/3ssEoGDgMmI/s72-c/Dibujo.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7418782953908644596.post-2352083545205052223</id><published>2010-04-01T03:32:00.000-07:00</published><updated>2010-04-01T03:46:30.042-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='generico'/><category scheme='http://www.blogger.com/atom/ns#' term='TDA'/><category scheme='http://www.blogger.com/atom/ns#' term='puntero a void'/><category scheme='http://www.blogger.com/atom/ns#' term='programacion'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>Código genérico en C</title><content type='html'>En C, voy a explicaros cómo introducir algo de genericidad en  vuestros programas C.&lt;br /&gt;Todos sabemos que C no es un lenguaje orientado  a objetos y que no conoce los conceptos de polimorfismo, sobrecarga...  entonces, ¿Como se puede escribir código genérico con este lenguaje? La  respuesta es sencilla: jugando con (&lt;span style="font-style: italic;"&gt;void  *).&lt;br /&gt;&lt;/span&gt;El puntero a  void puede representar nada&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;/span&gt;o cualquier cosa, así que  jugando con los &lt;span style="font-style: italic;"&gt;castings &lt;/span&gt;podemos  introducir un cierto grado de genericidad en nuestro código.&lt;br /&gt;De esta  manera, si tenemos un void *elemento, podemos hacer que ese elemento  sea una cadena, un entero, un float... o cualquier TDA&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Veamos  un ejemplo ilustrativo de una idea básica de cómo hacerlo.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PXahzV_MA9Y/S7R36U5wkNI/AAAAAAAAABU/BL_E_qS7IZw/s1600/generico.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 312px; height: 320px;" src="http://4.bp.blogspot.com/_PXahzV_MA9Y/S7R36U5wkNI/AAAAAAAAABU/BL_E_qS7IZw/s320/generico.png" alt="" id="BLOGGER_PHOTO_ID_5455116892579598546" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;En el ejemplo encuadro en rojo lo que sería nuestro TDA. Este TDA va a ser muy sencillito, solo incluye un elemento ( o muchos, si hacemos que elemento sea un array ).&lt;br /&gt;Lo que quería mostraros es como insertar en ese TDA un entero y una cadena.&lt;br /&gt;Realmente esto debería estar en 3 ficheros distintos. Por un lado tenemos el genérico, que sería el que implementa el TDA CeldaGenerica y contendría todas las operaciones que se pueden realizar sobre ella, es decir, todas las que se puedan realizar sobre void.&lt;br /&gt;Y por otro los otros 2, que serían los específicos del tipo de datos en concreto (cadena, entero, flotante...).&lt;br /&gt;Así, podemos tener un fichero genérico, por ejemplo, que implmente una lista de elementos, y otro más específico que haga uso del genérico que implemente una lista de enteros.&lt;br /&gt;&lt;br /&gt;Esto es todo, espero que os sirva de ayuda.&lt;br /&gt;SALUDOS!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7418782953908644596-2352083545205052223?l=elarmarioinformatico.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://elarmarioinformatico.blogspot.com/feeds/2352083545205052223/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://elarmarioinformatico.blogspot.com/2010/04/codigo-generico-en-c.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default/2352083545205052223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default/2352083545205052223'/><link rel='alternate' type='text/html' href='http://elarmarioinformatico.blogspot.com/2010/04/codigo-generico-en-c.html' title='Código genérico en C'/><author><name>cualquiera</name><uri>http://www.blogger.com/profile/06985416258894591114</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PXahzV_MA9Y/S7R36U5wkNI/AAAAAAAAABU/BL_E_qS7IZw/s72-c/generico.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7418782953908644596.post-6541913651352124077</id><published>2010-03-30T07:21:00.000-07:00</published><updated>2010-04-05T05:40:25.318-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='algoritmos'/><category scheme='http://www.blogger.com/atom/ns#' term='bioinspiracion'/><category scheme='http://www.blogger.com/atom/ns#' term='busqueda de soluciones'/><title type='text'>Algoritmos Bioinspirados</title><content type='html'>En nuestro entorno se dan una serie de acontencimientos que han inspirado algunos algoritmos de búsqueda de soluciones. Algoritmos genéticos y colonia de hormigas son algunos de ellos.&lt;br /&gt;Estos algoritmos ofrecen soluciones óptimas y pseudoóptimas, y su estudio ha demostrado que se pueden obtener muy buenos resultados en un tiempo en el que otros algoritmos de búsqueda en profundidad no se acercaría ni por asomo a una solución semejante.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;Genético:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El funcionamiento del genético se basa en la generación de estados mediante un conjunto de individuos, que forman una población.&lt;br /&gt;Cada individuo se compone de un conjunto de genes, que suelen ser 0 y 1s, aunque pueden ser enteros, caracteres... todo es cuestión de saber interpretar el estado y la solución obtenida según la representación del individuo escogida.&lt;br /&gt;Esta población se va modificando mediante la reproducción de unos individuos que han pasado un proceso de selección, mezclando sus genes. La probabilidad de que un individuo sea escogido para la reproducción es proporcional a lo bueno que sea ese individuo, para lo que deberemos implementar una función, denominada fitness, que nos da dicho valor.&lt;br /&gt;Una vez pasada la etapa de selección, se inicia la etapa de reproducción. Podemos elegir que los individuos se procreen 2 a 2 por la mitad, o con un random... escogiendo los genes que conservará el hijo de cada individuo padre y formando la siguiente generación.&lt;br /&gt;Ahora solo nos queda la etapa de mutación. En esta etapa se procede a mutar los genes, según cierta probabilidad, que suele ser muy baja. Una probabilidad alta nos da una convergencia lenta, pero una alta amplia el espacio de búsqueda cuando el algoritmo se ha estancado en una solución debido a que hemos alcanzado un máximo local.&lt;br /&gt;Este proceso se repite durante un número de iteraciones definido por el usuario.&lt;br /&gt;Una vez implementado el algoritmo, se trata de jugar con los parámetros probabilidad de selección, probabilidad de mutación, numero de individuos y número de iteraciones.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102); font-weight: bold;"&gt;Colonia de hormigas:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En la naturaleza, las hormigas encuentran el camino óptimo desde el alimento hasta el hormiguero ayudandose de una sustancia denominada feromona que es depositada por las hormigas y se evapora con el tiempo. A mayor cantidad de feromona mejor es el camino. Cada hormiga escogerá los caminos de mejor feromona. Así, inicialmente se mueven de forma aleatoria hasta encontrar el alimento. Es en la vuelta al hormiguero cuando depositan el rastro de feromona para que otras hormigas lo sigan.&lt;br /&gt;En esto es básicamente en lo que se basa este algoritmo.&lt;br /&gt;Las hormigas son agentes computacionales, que colaboran entre sí para encontrar la solución óptima, almacenando en cada paso cómo de bueno es el camino escogido.&lt;br /&gt;Existen varios tipos de algoritmos que implementan este comportamiento, pero solo me voy a centrar en explicar a nivel general en qué consiste la idea.&lt;br /&gt;Cada agente puede explorar el espacio de estados o explotar la feromona, según un valor probabilístico.&lt;br /&gt;Explorar el espacio de estados significará que avanzará al siguiente estado vecino, sin importarle la distancia ni la feromona.&lt;br /&gt;Al explotar la feromona el agente eligirá el siguiente estado en función de una probabilidad dada por la distancia al siguiente estado y por la feromona que hay en ese camino. Esta feromona como ya he comentado se decrementa con el tiempo.&lt;br /&gt;A la vuelta del recorrido el agente actualiza los niveles de feromona, indicando como de bueno ha sido el recorrido.&lt;br /&gt;&lt;br /&gt;Lo curioso de estos algoritmos es lo bien que funcionan basándose simplemente en parámetros de probabilidad, en el que escoger el siguiente estado es "pseudoaleatorio" en cierto modo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7418782953908644596-6541913651352124077?l=elarmarioinformatico.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://elarmarioinformatico.blogspot.com/feeds/6541913651352124077/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://elarmarioinformatico.blogspot.com/2010/03/algoritmos-bioinspirados.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default/6541913651352124077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default/6541913651352124077'/><link rel='alternate' type='text/html' href='http://elarmarioinformatico.blogspot.com/2010/03/algoritmos-bioinspirados.html' title='Algoritmos Bioinspirados'/><author><name>cualquiera</name><uri>http://www.blogger.com/profile/06985416258894591114</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7418782953908644596.post-8749670458913153437</id><published>2010-03-26T05:18:00.000-07:00</published><updated>2010-04-01T03:03:29.333-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='punteros'/><category scheme='http://www.blogger.com/atom/ns#' term='programacion'/><category scheme='http://www.blogger.com/atom/ns#' term='memory leaks'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><category scheme='http://www.blogger.com/atom/ns#' term='fugas de memoria'/><category scheme='http://www.blogger.com/atom/ns#' term='cores'/><title type='text'>Sobre punteros c</title><content type='html'>Empty your memory,&lt;br /&gt;with a free()…&lt;br /&gt;like a pointer!&lt;br /&gt;&lt;br /&gt;If you      cast a pointer to a integer,&lt;br /&gt;it becomes the integer,&lt;br /&gt;if you cast  a     pointer to a struct,&lt;br /&gt;it becomes the struct…&lt;br /&gt;The pointer can      crash…,&lt;br /&gt;and can Overflow…&lt;br /&gt;Be a pointer my friend…&lt;br /&gt;&lt;br /&gt;¿Quién   no    ha tenido nunca más de un quebradero de cabeza con una violación   de    segmento, o un core? A veces te vale la excusa de "es que en  casa  sí    funciona...", pero créeme, en la mayoría de los casos no.&lt;br /&gt;&lt;br /&gt;Trabajar      con punteros es relativamente sencillo si tienes una idea clara de     cómo  referenciar a memoria y si sigues una metodología sistemática a   la   hora  de hacerlo.&lt;br /&gt;Intenta entender los siguientes aspectos, es     posible que  una vez entendidos disminuyas considerablemente el  número    de cores o  fallos provocados por accesos a memoria:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;A  la    hora de  realizar alguna comparación, ten cuidado cuando las  variables    implicadas  sean punteros, es posible que no quieras  comparar el VALOR    DEL PUNTERO  (es decir, la dirección de memoria) y  que lo que quieras    comparar  realmente es el VALOR al que apunta el  puntero (es decir,  el   valor  contenido en memoria).&lt;/li&gt;&lt;li&gt;Asegurate  de que liberas los    punteros  para evitar fugas de memoria (o memory  leaks). Esto es un    problema  sobretodo en proyectos grandes.  Imagínate que en tu programa    realizas  una llamada a una función que  reserva 1 KB, que olvidas    liberar. Esto no  es problema si tu  programa terminase, pero si actua    como demonio, en  segundo plano... y  además no realiza esa llamada una    vez, sino varias,  tu programa  estaría consumiendo de forma innecesaria    memoria del sistema  de  forma incremental.&lt;/li&gt;&lt;li&gt;De igual modo que  en  1.-, ten cuidado a  la  hora de asignar valores a punteros. Tenemos  una   tendencia a copiar  un  puntero en otro puntero con el operador  igual.   Esto solo es  válido si  lo que quieres copiar son las  referencias  a   memoria. Si  no, deberías  copiar elemento a elemento o  mediante un   memcpy...&lt;/li&gt;&lt;li&gt;A  la hora de  trabajar con paso por  referencia, es más   comodo reservar  la variable que  vas a pasar por  referencia de forma   estática y en  la llamada al  procedimiento/función  pasarle la dirección   con el  operador &amp;amp;.&lt;/li&gt;&lt;li&gt;Recuerda  que si  reservas memoria dentro   de  un procedimiento/función la estás   reservando en pila, por lo que    cuando llames a otras 1 o 2 funciones  más  se machacará, probocando un    core. Si quieres reservar memoria  dentro de  un procedimiento para  una   variable que le pasas por  referencia debes  pasar el puntero por    referencia, y no la variable.  Es decir, la  signatura del parámetro  debe   ser "puntero a puntero" y  no "puntero"&lt;/li&gt;&lt;li&gt;Ten  en cuenta  que la   mayoría de las veces que  declaras un puntero debes  reservar  memoria, a   no ser que lo vayas a  usar como un puntero auxiliar o   algo por el   estilo.&lt;/li&gt;&lt;li&gt;Presta  especial atención a no acceder a   posiciones del   puntero que  sobrepasen lo que has reservado para el. Recuerda siempre que debes indexar entre 0 y TAMAÑO-1.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;Veamos un ejemplo del     caso 1.-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- inicio codigo contador --&gt;&lt;a onblur="try     {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PXahzV_MA9Y/S7GkzNmjgsI/AAAAAAAAAAU/t9fNFckUuPs/s1600/30-03-2010+9-08-45.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 318px;" src="http://3.bp.blogspot.com/_PXahzV_MA9Y/S7GkzNmjgsI/AAAAAAAAAAU/t9fNFckUuPs/s320/30-03-2010+9-08-45.png" alt="" id="BLOGGER_PHOTO_ID_5454321823454036674" border="0" /&gt;&lt;/a&gt;&lt;tama&amp;amp;&amp;amp;*(ptr_int1+i)==*(ptr_int2+i);i++);&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/tama&amp;amp;&amp;amp;*(ptr_int1+i)==*(ptr_int2+i);i++);&gt;&lt;span style="text-decoration: underline;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;tama&amp;amp;&amp;amp;*(ptr_int1+i)==*(ptr_int2+i);i++);&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Este      ejemplo está testeado en un ubuntu 9.10.&lt;br /&gt;Los resultados son los      esperados:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;La primera comparación, en la que comparamos  los     punteros, nos dice que no son iguales.&lt;/li&gt;&lt;li&gt;La segunda, en la  que     comparamos el contenido de cada posición, nos dice que sí.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Si      te fijas en cómo comparo elemento a elemento, sumo -i- al puntero.      Hubiera dado lo mismo si lo hubiese hecho con -[i]-, pero es por      diferenciar un poco entre memoria estática y dinámica.&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;Efectos del caso 2.-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Veamos      un ejemplo de como producir una fuga de forma "involuntaria".&lt;br /&gt;&lt;br /&gt;&lt;/tama&amp;amp;&amp;amp;*(ptr_int1+i)==*(ptr_int2+i);i++);&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7HU3mWXP7I/AAAAAAAAAAs/VJkydL9UMQQ/s1600/codigo_fuga.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 146px;" src="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7HU3mWXP7I/AAAAAAAAAAs/VJkydL9UMQQ/s320/codigo_fuga.png" alt="" id="BLOGGER_PHOTO_ID_5454374675374620594" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7Gj-mlPb8I/AAAAAAAAAAM/zio14TSHmlA/s1600/30-03-2010+9-08-45.png"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Podemos      observar en el código que la memoria reservada en &lt;span style="font-style: italic;"&gt;foo() &lt;/span&gt;no se libera, y que se llama a      dicha función en el código de forma indefinida mediante un while(1),     por  lo que si este proceso se ejecuta en segundo plano provocará un      incremento del uso de memoria a medida que pase el tiempo.&lt;br /&gt;&lt;br /&gt;Una      forma de monitorizar el uso de memoria en linux es a través de ps   aux,    observando la columna stat:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try    {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7HVWdCQ8iI/AAAAAAAAAA0/n1kYATtNXAc/s1600/fuga.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 91px;" src="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7HVWdCQ8iI/AAAAAAAAAA0/n1kYATtNXAc/s320/fuga.png" alt="" id="BLOGGER_PHOTO_ID_5454375205450347042" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;Efectos  del caso 3.-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En  rojo encuadro el error habitual y en azul una forma correcta de hacerlo.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7IGUI4sKdI/AAAAAAAAABM/XOoN4-JqHPE/s1600/pila.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 300px; height: 320px;" src="http://1.bp.blogspot.com/_PXahzV_MA9Y/S7IGUI4sKdI/AAAAAAAAABM/XOoN4-JqHPE/s320/pila.png" alt="" id="BLOGGER_PHOTO_ID_5454429041751501266" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;La parte comentada sería la forma incorrecta de hacerlo. Está así porque da un core. Los printfs están colocados a posta para que se machaque la pila, si no estuvieran es posible que no se pudiera reproducir el core.&lt;br /&gt;Si te fijas, al llamar a foo2, el parámetro viene precedido del símbolo &amp;amp;. Esto significa que es la dirección de esa variable que le pasamos como parámetro, que sería la dirección del puntero, es decir, un puntero a puntero, cumpliendo con la signatura de la cabecera de la función.&lt;br /&gt;Esto es todo de momento...&lt;br /&gt;SALUDOS!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://contador-de-visitas.com/"&gt;&lt;img style="border: 0px solid; display: inline;" alt="contador de visitas" src="http://contador-de-visitas.com/hit.php?id=251897&amp;amp;counter=34" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;!-- fin codigo contador --&gt;&lt;br /&gt;&lt;a href="http://www.chollovuelos.com/" target="_blank"&gt;Vuelos Baratos&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.anuns.co.za/"&gt;Anuns&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.directorioblogs.es/" title="Blogs"&gt;&lt;img src="http://www.directorioblogs.es/i/directorioblogs.gif" alt="Blogs" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.zapin.info/"&gt;&lt;img src="http://www.zapin.info/directorio-blogs/zapin.gif" alt="blogs" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7418782953908644596-8749670458913153437?l=elarmarioinformatico.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://elarmarioinformatico.blogspot.com/feeds/8749670458913153437/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://elarmarioinformatico.blogspot.com/2010/03/empty-your-memory-with-free-like.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default/8749670458913153437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7418782953908644596/posts/default/8749670458913153437'/><link rel='alternate' type='text/html' href='http://elarmarioinformatico.blogspot.com/2010/03/empty-your-memory-with-free-like.html' title='Sobre punteros c'/><author><name>cualquiera</name><uri>http://www.blogger.com/profile/06985416258894591114</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_PXahzV_MA9Y/S7GkzNmjgsI/AAAAAAAAAAU/t9fNFckUuPs/s72-c/30-03-2010+9-08-45.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
