2011-01-03 9 views
8

Así que hay varias maneras de ejecutar todos los elementos de una matriz a través de un selector o bloque de código. makeObjectsPerformSelector: y másCómo procesar una matriz EN PARALELO

Si tiene 4 o 16 núcleos a mano, es posible que desee enviar todo el procesamiento a diferentes procesos.

Incluso en iOS, podría ser sensato enviarlos a todos, o al menos dejar que se terminen de la forma en que sople el viento.

¿Cuál es la mejor y más sencilla manera de hacer esto en el medio del cacao??

Una vez más, lo que si desea enviar a la basura para ser terminado en cualquier momento, es decir, no espere a que la enumeración para terminar antes de ejecutar la siguiente instrucción ...?

Respuesta

9

Si usted puede dirigirse a iOS 4 o Mac OS X 10.6+, utilice Grand Central Dispatch (y estoy usando una categoría porque creo que son cool):

#import <dispatch/dispatch.h> 

@interface NSArray (DDAsynchronousAdditions) 

- (void) makeObjectsPerformSelectorAsynchronously:(SEL)selector; 
- (void) makeObjectsPerformSelectorAsynchronously:(SEL)selector withObject:(id)object; 

@end 

@implementation NSArray (DDAsynchronousAdditions) 

- (void) makeObjectsPerformSelectorAsynchronously:(SEL)selector { 
    [self makeObjectsPerformSelectorAsynchronously:selector withObject:nil]; 
} 

- (void) makeObjectsPerformSelectorAsynchronously:(SEL)selector withObject:(id)object { 
    for (id element in self) { 
    dispatch_async(dispatch_get_global_queue(0,0), ^{ 
     [element performSelector:selector withObject:object]; 
    }); 
    } 
} 

@end 

//elsewhere: 

[myArray makeObjectsPerformSelectorAsynchronously:@selector(doFoo)]; 

O, si no quieren utilizar una categoría ...

[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL * stop) { 
    dispatch_async(dispatch_get_global_queue(0,0), ^{ 
    [obj performSelector:@selector(doFoo)]; 
    }; 
}]; 
+0

buena solución :) – Moszi

+0

@ Joe me respondió ayer :) –

+0

@ Joe el '0,0' son para conseguir la cola global de la prioridad por defecto (' 0'), y el segundo parámetro siempre es 0 (porque los documentos lo dicen). Y si tienes un bloque en una variable 'myBlock', lo invocas así:' myBlock() ' –

10

Si desea concurrencia y el comportamiento síncrono (es decir, esperar a que la enumeración para terminar antes de ejecutar la siguiente instrucción), -[NSArray enumerateObjectsWithOptions:usingBlock:] hará que si se pasa el NSEnumerationConcurrent opción. Este método está disponible en Mac OS 10.6+ e iOS 4.0+.

Si desea un comportamiento asincrónico, puede utilizar una de las soluciones estándar de subprocesos múltiples como NSOperation o GCD combinados con -enumerateObjectsWithOptions:usingBlock:. Por ejemplo,

dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    [array enumerateObjectsWithOptions:NSEnumerationConcurrent 
     usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
      // do something with obj 
     }]; 
    }); 
+1

El objetivo de esta opción es distribuir el trabajo entre los núcleos disponibles. ¿Qué más podría hacer? –

+0

Ese método usa GCD internamente, pero hace un poco de trabajo por lotes para evitar una sobrecarga innecesaria. Yo recomendaría probarlo antes de hacer tu propio. –

+0

@Joe Blow: puede usar cualquiera de las soluciones habituales para subprocesamiento múltiple, como NSOperation o GCD. Por ejemplo, podría GCD-async-dispatch un bloque que envíe '-enumerateObjectsWithOptions: usingBlock:' a la matriz. –

Cuestiones relacionadas