2013-08-05 12 views
5

Mi è stato detto che potevo usare Grand Central Dispatch per eseguire n processi contemporaneamente, in modo asincrono. La documentazione diceva che se i processi fossero in un ciclo for, potrei usare la funzione dispatch_apply. Ma ora che sta dicendoDispatch_apply è sincrono o asincrono?

Si noti che è dispatch_apply sincrono, in modo da tutti i blocchi applicati avrà completato nel momento in cui ritorna.

Ciò significa che i blocchi inviati a una coda utilizzando dispatch_apply vengono eseguiti in ordine? In tal caso, che senso ha utilizzare la concorrenza? Il rallentamento non sarà lo stesso?

risposta

13

dispatch_apply è, come indicato nei documenti, sincrono. Esegue un blocco sulla coda specificata in parallelo (se possibile) e attende finché tutti i blocchi non ritornano. Se si desidera eseguire un blocco solo una volta in modo asincrono, utilizzare dispatch_async, se si desidera eseguire un blocco più volte in parallelo senza bloccare la vostra coda corrente, basta chiamare dispatch_apply entro dispatch_async:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 
    dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(size_t size) { 
     NSLog(@"%lu", size); 
    }); 
}); 
+0

Impressionante, questo è esattamente quello che voglio fare. Grazie. – Jessica

6

Lo scopo del sincronodispatch_apply è a in modo asincrono invia le interazioni del loop interno alle risorse di elaborazione parallele disponibili. Pertanto, le prestazioni globali del circuito potrebbero accelerare.

Prestazioni del ciclo più veloce? Molto probabilmente, sì. (vedi avvertenza)

Blocca il thread che chiama dispatch_apply? Sì, proprio come i blocchi di loop fino al completamento.

Per GCD, dispatch_apply è sincrono poiché dispatch_apply non tornerà fino tutto ilasincrono, parallele compiti che crea dispatch_apply hanno completato.

Tuttavia, ogni singola attività accodato da dispatch_apply può funzionare come concomitante asincrono compiti se il bersaglio queue è asincrono.

Per esempio in Swift:

let batchCount: Int = 10 
let queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) 
dispatch_apply(batchCount, queue) { 
    (i: Int) -> Void in 
    print(i, terminator: " ") 
} 
print("\ndispatch_apply QOS_CLASS_UTILITY queue completed") 

cede uscita ordinata come:

0 8 1 9 2 3 4 5 6 7 
dispatch_apply QOS_CLASS_UTILITY queue completed 

Quindi, dispatch_apply sincrono blocchi quando viene chiamato, ma la "partita" delle attività generato da dispatch_apply possono essere eseguiti contemporaneamente, in modo asincrono, in parallelo tra loro.

Tenere presente l'avvertenza che ...

il lavoro svolto durante ogni iterazione è distinta dal lavoro eseguiti durante tutte le altre iterazioni, e l'ordine in cui ciascun successivo ciclo finito è irrilevante

Inoltre, nota che l'utilizzo di una coda seriale per le attività del ciclo interno non avrà alcun guadagno in termini di prestazioni.

Sebbene l'utilizzo di una coda di serie è ammissibile e fa la cosa giusta per il codice, utilizzando tale coda è alcun vantaggio reale di prestazioni sopra lasciando l'anello al suo posto.

0

È possibile ottenere velocità di prestazioni fino utilizzando gcl_create_dispatch_queue() con dispatch_apply()

Ad esempio:

@import Foundation; 
@import OpenCL;  // gcl_create_dispatch_queue() 

int main() { 
     dispatch_queue_t queue = gcl_create_dispatch_queue(CL_DEVICE_TYPE_ALL, NULL); 
     dispatch_apply(10, queue, ^(size_t t) { 
      // some code here 
     }); 
} 

Maggiori informazioni: OpenCL Programming Guide for Mac

Problemi correlati