2008-09-11 10 views
7

Actualmente estoy diseñando una aplicación que tiene un módulo que cargará grandes cantidades de datos de una base de datos y los reducirá a un conjunto mucho más pequeño según varios cálculos, según las circunstancias.¿Cómo le digo a una máquina multi-core/multi-CPU que procese llamadas de función en un bucle en paralelo?

Muchas de las operaciones más intensivas se comportan de manera determinista y se prestan a un procesamiento paralelo.

Siempre que tenga un ciclo que itere sobre una gran cantidad de fragmentos de datos que llegan del DB y para cada uno llame a una función determinística sin efectos secundarios, ¿cómo lo haré para que el programa no espere a que la función volver, pero más bien establece las próximas llamadas en marcha, por lo que podrían procesarse en paralelo? Un enfoque ingenuo para demostrar el principio me haría por ahora.

He leído el documento de MapReduce de Google y si bien podría utilizar el principio general en varios lugares, por ahora, no me enfocaré en grandes grupos, sino que será un solo multi-core o multi-CPU máquina para la versión 1.0. Por lo tanto, actualmente no estoy seguro de si realmente puedo usar la biblioteca o tendré que rodar una versión básica embrutecida.

Estoy en una etapa inicial del proceso de diseño y hasta ahora estoy apuntando a C-algo (para los bits críticos de velocidad) y Python (para los bits críticos de productividad) como mis idiomas. Si hay razones convincentes, podría cambiar, pero hasta ahora estoy contento con mi elección.

Tenga en cuenta que soy consciente de que podría llevar más tiempo recuperar el siguiente fragmento de la base de datos que procesar el actual y todo el proceso estaría vinculado a E/S. Sin embargo, supongo que por el momento no es así y, en la práctica, utilizo un clúster de db o almacenamiento en memoria caché u otra cosa para no estar enlazado a E/S en este punto.

+1

Podría actualizar el texto para agregar un enlace al documento google mapreduce, creo que es un recurso excelente (http://labs.google.com/papers/mapreduce.html). –

Respuesta

2

Me puede estar faltando algo aquí, pero esto parece bastante sencillo usar pthreads.

Configura un pequeño grupo de subprocesos con N subprocesos y tiene un subproceso para controlarlos a todos.

El hilo principal simplemente se sienta en un bucle haciendo algo como:

  1. fragmento de datos obtener de DB
  2. Buscar siguiente hilo suelto Si ningún hilo está libre luego esperar
  3. mano sobre trozo de subproceso de trabajo
  4. volver y conseguir siguiente fragmento de DB

Mientras tanto, los subprocesos de trabajo que sentarse y no hacer:

  1. Marcos mí mismo como libre de
  2. Espere a que el hilo mástil para dame un fragmento de datos
  3. Proceso de la porción de datos
  4. Marcos mí mismo como libre de nuevo

El método por el que implemente esto puede ser tan simple como dos arreglos controlados por mutex. Uno tiene los hilos trabajados en él (el grupo de hilos) y el otro indicado si cada hilo correspondiente está libre u ocupado.

Tweak N a su gusto ...

3

Puede implementar el algoritmo de MapReduce de Google sin tener físicamente máquinas separadas. Simplemente considere cada una de esas "máquinas" como "hilos". Los hilos se distribuyen automáticamente en máquinas multi-core.

2

Si está trabajando con un compilador que lo admitirá, le sugiero que consulte http://www.openmp.org para obtener una forma de anotar el código de tal manera que ciertos bucles se paralelizarán.

Hace mucho más también, y puede que le resulte muy útil.

Su página web informa que gcc4.2 admitirá openmp, por ejemplo.

3

Si aún planea usar Python, es posible que desee echar un vistazo a Processing. Utiliza procesos en lugar de hilos para computación paralela (debido a Python GIL) y proporciona clases para distribuir "elementos de trabajo" en varios procesos. Utilización de la clase de la piscina, puede escribir código como el siguiente:

import processing 

def worker(i): 
    return i*i 
num_workers = 2 
pool = processing.Pool(num_workers) 
result = pool.imap(worker, range(100000)) 

Esta es una versión paralela de itertools.imap, que distribuye las llamadas a los procesos. También puede utilizar los métodos apply_async de la piscina y almacenar objetos de resultado perezosos en una lista:

results = [] 
for i in range(10000): 
    results.append(pool.apply_async(worker, i)) 

Para mayor referencia, ver the documentation of the Pool class.

Gotchas:

  • Processing utiliza tenedor(), así que hay que tener cuidado en Win32
  • objetos transferidos entre los procesos tienen que ser pickleable
  • si los trabajadores son relativamente rápido, se puede ajustar chunksize, es decir el número de elementos de trabajo enviar a un proceso de trabajo en un lote
  • processing.Pool utiliza un subproceso de fondo
0

El mismo grupo de subprocesos se usa en Java. Pero los subprocesos de los grupos de subprocesos son serializables y se envían a otras computadoras y se deserializan para ejecutarse.

0

He desarrollado una biblioteca MapReduce para uso multiproceso/multi-núcleo en un solo servidor. La biblioteca se encarga de todo y el usuario solo debe implementar Map and Reduce. Se posiciona como una biblioteca de Boost, pero todavía no se acepta como una lib formal.Consulte http://www.craighenderson.co.uk/mapreduce

0

Puede estar interesado en examinar el código de libdispatch, que es la implementación de código abierto del Grand Central Dispatch de Apple.

0

Intel TBB o boost :: mpi también pueden ser de su interés.

Cuestiones relacionadas