Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Algunas preguntas de threads

Iniciado por davidgf, 22 de Noviembre de 2008, 08:09:14 PM

« anterior - próximo »

davidgf

Hola gente.

Tenía algunas preguntas de threads.

- Si varios threads acceden para escribir a un mismo array pero en posiciones diferentes pasa algo? Explotará mi código?
- Y para leer? Si leo puedo leer la misma posición des de varios hilos?
- Si simplemente quiero hacer cosas simples, del tipo distribuir la faena en varios threads para hacerla más rapido, me recomendais SDL? Sólo usaria algun que otro semáforo para escribir datos compartidos entre threads.

Mi objetivo era tener un array donde ir escribiendo el resultado de un algoritmo. Se haria por bloques. Cada hilo calcularia una serie de datos leidas de un vector comun a todos los hilos y lo escribiría en un bloque de posiciones del array, previamente con un semaforo en una variable que apunte al inicio del espacio libre del array me reservaria el espacio necesario.

Qué pensáis? Soy rebuscado o qué?

Gracias!

David
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

zxs

Cita de: davidgf en 22 de Noviembre de 2008, 08:09:14 PM
Hola gente.

Tenía algunas preguntas de threads.

- Si varios threads acceden para escribir a un mismo array pero en posiciones diferentes pasa algo? Explotará mi código?
- Y para leer? Si leo puedo leer la misma posición des de varios hilos?
- Si simplemente quiero hacer cosas simples, del tipo distribuir la faena en varios threads para hacerla más rapido, me recomendais SDL? Sólo usaria algun que otro semáforo para escribir datos compartidos entre threads.

Mi objetivo era tener un array donde ir escribiendo el resultado de un algoritmo. Se haria por bloques. Cada hilo calcularia una serie de datos leidas de un vector comun a todos los hilos y lo escribiría en un bloque de posiciones del array, previamente con un semaforo en una variable que apunte al inicio del espacio libre del array me reservaria el espacio necesario.

Qué pensáis? Soy rebuscado o qué?

Gracias!

David

pues no lo se, no creo que explote, creo recordar que en un código en el curro tennemos una cola, la accedemos mediante semáforos
entre varios threads y todavía esa parte del código no ha cascado  :P


Leoheart

Me parece, por lo que me contó un profesor mio, si las variables que van a acceder cada uno de los hilos no son comunes ( como es tu caso) no vale la pena hacerlo por hilos.
Si son varias las funciones que van a modificar la matriz( toda ella o posiciones en comun) si que es rentable meterle hilos con un semaforo para que no te pete.;)

Saludos!
oding!

davidgf

Ya, os comento es que deberia tener pocos semaforos..

El algoritmo extruye una shadow volume de un objeto y copia los vertices a un array muy grande para, una vez hecho todas la iteraciones por cada objeto, se pueda renderizar el array entero. La gracia estaria en que pudiera escribir en ese array en posiciones DIFERENTES para hacerlo rapidito. Así con los threads podría extruir varios objetos a la vez y acabar mucho antes. Pero claro, si he de poner un semáforo no se si valdrá la pena no?

Es decir, para aclarar, cada thread tendria un trozo de ese array para su uso. Así el thread 1 diria me quedo del 0 al 234 y pondria variable ocupado=234, el siguiente thread incrementaria ocupado para alcanzar lo que necesitara.

Me parece que haré pruebas que es lo mejor en estos casos.

Saludos y gracias por todo!

David
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

Warchief

Si el array es fijo en memoria (no provoca auto-resize) y cada hilo utiliza posiciones distintas de memoria, NO se necesita sincronización en el acceso; sólo hará falta un join al final para comprobar cuándo todos los hilos han terminado sus respectivas regiones. Este es el caso sencillo en el que divides el trabajo en N trozos para N hilos y donde no se solapa la variable.

Si el número de trozos es mayor que el de hilos (ej: 32 trozos para 2 hilos), de forma que cada hilo pida un trozo tan pronto como haya terminado el anterior, sí se necesita sincronización para la petición (compartida), pero no para el acceso al array. Esto se hace cuando hay muchas tareas que deben ser realizadas tan pronto como haya un hilo disponible (ya que podrían ejecutar en procesadores distintos o incluso ordenadores distintos), pero no es tu caso. :)

En resumen, no necesitas semáforo o mutex, para el acceso al array; pero no olvides sincronizar los hilos al final, para que unos esperen a otros y poder volcar el array en el momento preciso.

davidgf

Esa es la respuesta que quería!
Mil gracias Warchief!!!

Así pues con un mutex para pedir más trabajo lo tengo solucionado!
De dónde sacáis esas cosas? He sido incapaz de encontrar páginas web dónde se expliquen esos detalles con claridad.

Muchisimas gracias a todos.

David
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

flipper83

si es c++, ten cuidado ya que el compilador puede reordenar las instrucciones y que te ocurran cosas raras :S, para q no ocurra eso hay q definir la variable de una manera especial, y ahora no me acuerdo,mañana por la mañana pongo como XD.
un cobarde forero en el tanatorio al mes sería un placentero trofeo digno de merecer

Buffon

Cita de: davidgf en 23 de Noviembre de 2008, 12:21:27 PM
Esa es la respuesta que quería!
Mil gracias Warchief!!!

Así pues con un mutex para pedir más trabajo lo tengo solucionado!
De dónde sacáis esas cosas? He sido incapaz de encontrar páginas web dónde se expliquen esos detalles con claridad.

Muchisimas gracias a todos.

David

probando :)

Warchief

#8
Y de la carrera, donde obligan a paralelizar algunos programas. :)

Ten en cuenta que el tema de los workers es la solución cuando tienes muchas tareas y varios hilos/procesadores; cuando tienes pocos hilos, se puede perder un tiempo valiosísimo en la sincronización:
Ej: 200 tareas no muy rápidas, 16 hilos (en procesadores distintos) = genial, se reparten las tareas según van terminando
vs: 200 tareas rápidas, 2 hilos = exceso de sincronización

Por ejemplo, si tienes un array de 200 variables, puede ser mejor partir en 2, 100 para cada hilo, y sincronizar en el join (al terminar ambos), en vez de partir en 20 trozos de 10 variables y hacer la sincronización en la petición cada vez que un hilo termina 10 variables. Depende de la arquitectura de la apliación, del hardware y del problema a resolver.

En cualquier caso, si quieres hacer workers (N tareas esperando un hilo que las ejecute):
http://en.wikipedia.org/wiki/Thread_pool_pattern

En tu caso ten en cuenta que el array debe quedar disponible después de haber realizado el cálculo, por lo que los hilos deben quedar en espera o ponerse a trabajar en otro array, mientras el recién calculado se vuelca al destino.

Suerte!

Enlaces.

SDL:
http://www.libsdl.org/intro.en/usingthreads.html
http://lazyfoo.net/SDL_tutorials/index.php Lecciones 33,34,35

Otras:
http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html (boost es portable)
http://profesores.elo.utfsm.cl/~agv/elo330/2s06/lectures/POSIX_threads/POSIX_Threads_Synchronization.html (posix es para sistemas unix)


<edit>
Como ejemplo, comentaré que yo paralelicé un algoritmo de conversión de imágenes de true color a grayscale. El problema es sencillo de resolver, ya que hay una fórmula (no recuerdo, pero digamos que Gris = 0.x * rojo + 0.y * verde + 0.z azul). El resultado fue que la versión secuencial (1 hilo) era siempre más rápida que las distribuidas entre 2, 4 y 8 ordenadores, ya que el hecho de enviar cada sección de la imagen a cada ordenador (paralelización en red), y después juntar todos los trozos en la imagen resultado (también envío por red), era mucho más costoso que la ganancia de haber calculado las operaciones en paralelo.

Con imágenes mucho mayores, el tiempo de sincronización/envío se hace cada vez menor comparado con el tiempo secuencial de la operación; pero en la práctica no fue rentable puesto que las imágenes normales suelen ser << 4096x4096.

Por eso, depende del problema. Si el algoritmo es muy complejo, sí puede verse beneficiado. Si no, la sincronización puede perjudicar el rendimiento; también cuando los hilos corren sobre la misma máquina, claro.
</edit>

AK47

A modo de colorario de lo que ha dicho Warchief, si tienes N modelos a extruir, tienes un trabajo perfectamente paralelizable: a cada hilo le asignas, antes de que empiecen a hacer nada, una serie de modelos (si tienes 10 modelos y 2 hilos, pues 5 modelos a cada uno). Así los hilos podrán trabajar a destajo sin necesidad de sincronizar sus tareas, y sólo debes hacer el join una vez que los lances.

Buffon

Además de comentar que normalmente cuando trabajas con threads es por la necesidad y no por la posibilidad de acceder a un recurso global.

davidgf

En principio el objetivo es extruir los modelos por threads y que cada thread vaya cogiendo modelos a medida que acaba, ya que habrá modelos de diferente complejidad.

Todos escribirán en el mismo vector de destino y una variable gobal dirá a partir de que posición del vector éste está disponible para escribir.
Entonces usando un semáforo un thread incrementará esa variable evitando que los demás threads escriban en esa región que acabada de incrementar.
Así pues en ningun momento un thread invadirá el espacio de otro y sólo es usará un semáforo en esa variable global que sí es común.

Me miro vuestros enlaces que son interesantísimos!

Muchas gracias a todos!

David
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.