2011-08-27 18 views
23

Esiste una buona documentazione su quanti thread vengono creati da GCD? Al WWDC, ci hanno detto che è modellato intorno ai core della CPU. Tuttavia, se chiamo questo esempio:Numero di thread creati da GCD?

for (int i=1; i<30000; i++) { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [NSThread sleepForTimeInterval:100000]; 
    }); 
} 

apre 66 thread, anche su un iPad1. (Apre anche 66 thread quando viene chiamato su Lion in modo nativo). Perché 66?

risposta

24

Primo, 66 == 64 (la dimensione massima del pool di thread GCD) + il thread principale + qualche altro thread casuale non GCD.

In secondo luogo, GCD non è magico. È ottimizzato per mantenere la CPU occupata con il codice che è principalmente legato alla CPU. La "magia" di GCD è che crea dinamicamente più thread rispetto alle CPU quando gli elementi di lavoro non sono intenzionali e attendono brevemente il completamento delle operazioni.

Detto questo, il codice può confondere lo schedulatore GCD intenzionalmente dormendo o aspettando eventi invece di utilizzare le fonti di invio per attendere gli eventi. In questi scenari, il blocco di lavoro sta effettivamente implementando il proprio scheduler e pertanto GCD deve presupporre che il thread sia stato cooptato dal pool di thread. In breve, il pool di thread funzionerà in modo ottimale se il codice preferisce dispatch_after() su "sleep()" come API e origini di invio su loop di eventi artigianali (Unix select()/poll(), Cocoa runloops o Variabili di condizione POSIX).

+1

"è stato cooptato dal pool di thread" Cosa intendi per cooptato? Intendi dire che il sonno o altri riagganciati saranno interpretati come attività al 100% così da parlare e quindi la discussione non sarà disponibile per l'uso con dispacci aggiuntivi? –

+1

Certo sarebbe bello se fosse possibile fornire un riferimento per questo reclamo sulle dimensioni del pool di thread: non riesco a trovarne uno ovunque. –

1

La documentazione evita di menzionare il numero di thread creati. Principalmente perché il numero ottimale di thread dipende fortemente dal contesto.

Un problema con Grand Cendral Dispatch è che genererà un nuovo thread se un task in esecuzione blocca. Cioè, dovresti evitare di bloccare quando usi GCD avendo più thread di quanto i core non siano ottimali.

Nel tuo caso, GCD rileva che l'attività è inattiva e genera un nuovo thread per l'attività successiva.

Perché 66 è il limite è oltre me.

+0

Non riesco a credere che 66 sia un numero ottimale, se la documentazione mi dice che ogni thread consuma circa mezzo megabyte di ram. (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html) Quindi, con 66 thread, abbiamo un sovraccarico di circa 30 mega, che è la metà del limite di 64MB di iOS in totale. – steipete

+0

@steipete Il thread costa anche il cambio di contesto. Quindi la memoria non dovrebbe essere l'unico fattore per decidere il limite. – Eonil

+1

@steipete dallo stesso documento "ma le pagine effettive associate a quella memoria non vengono create finché non sono necessarie.". Quindi, il mezzo meg di spazio di stack viene rivendicato solo quando viene utilizzato (pagina per pagina, cioè se il thread richiede solo 2 pagine di stack, spreca solo così tanto). Inoltre, Eonil, ora abbiamo CPU multi-core dove il costo del cambio di contesto è meno di un problema (dato che "solo" esegui il numero di thread uguale o inferiore al numero di core) – tofi9