2010-10-13 13 views
15

Nel runtime di concorrenza introdotto in VS2010, esiste una classe concurrent_queue. Ha una funzione try_pop() non bloccante.
Simile in Intel Thread Building Blocks (TBB), la chiamata di blocco pop() è stata rimossa passando dalla versione 2.1 alla 2.2.perché concurrent_queue non è bloccante?

Mi chiedo quale sia il problema con una chiamata di blocco. Perché è stato rimosso da TBB? E perché non esiste un blocco concurrent_queue?

Sono in una situazione in cui ho bisogno di una coda concomitante di blocco e non voglio un'attesa occupata. Oltre alla scrittura di una coda, c'è un'altra possibilità nel runtime di concorrenza?

risposta

25

Da a comment from Arch Robison, e non ottiene molto di più di quello "horse's mouth"(a):


di PPL concurrent_queue non ha il blocco pop, quindi non fa tbb::strict_ppl::concurrent_queue. Il pop di blocco è disponibile in tbb::concurrent_bounded_queue.

L'argomento di progettazione per omettere il pop di blocco è che in molti casi la sincronizzazione per il blocco viene fornita al di fuori della coda, nel qual caso l'implementazione del blocco all'interno della coda diventa un sovraccarico non necessario.

D'altra parte, il pop di blocco del vecchio tbb::concurrent_queue era popolare tra gli utenti che non avevano la sincronizzazione esterna.

Quindi abbiamo diviso la funzionalità. I casi d'uso che non richiedono il blocco o il limite possono utilizzare il nuovo tbb::concurrent_queue e utilizzare i casi che ne hanno bisogno possono utilizzare tbb::concurrent_bounded_queue.


(a) arco è l'architetto del Threading Building Blocks.

4

Se è necessario un pop di blocco senza un'attesa, è necessario un metodo di segnalazione. Ciò implica la sincronizzazione tra pusher e poper e la coda non è più priva di (costose) primitive di sincronizzazione. Fondamentalmente si ottiene una normale coda sincronizzata con una variabile di condizione che viene utilizzata per notificare i poppers di push, che non è nella spirale delle collezioni simultanee *.

0

Non c'è alcuna situazione, dal punto di vista della coda, che sia necessario per bloccare o inserire un inserto o uno. Il fatto che potrebbe essere necessario bloccare e attendere un inserto è irrilevante.

È possibile ottenere la funzionalità desiderata utilizzando una variabile di condizione o un semaforo di conteggio o qualcosa di simile (qualunque sia la specifica API fornita). Il tuo problema non è con il blocco/non-blocco; sembra un classico produttore-consumatore.

+2

Con un blocco 'pop', è possibile implementare * * "classico produttore-consumatore" utilizzando TBB in circa due righe di codice, senza la necessità di scrivere alcun primitive di sincronizzazione da soli. (Il consumatore usa 'while (true) consuma (Q.pop());' e il produttore fa 'while (true) Q.push (produce());'.) Senza un 'pop' di blocco, lo stesso problema richiede almeno il doppio del codice: vale a dire, contabilità una variabile di condizione extra per coda. Ma come dice paxdiablo, 'tbb :: concurrent_bounded_queue' continua a fornire la funzionalità di blocco' pop', ed è fondamentalmente una sostituzione drop-in per 'concurrent_queue'. – Quuxplusone

2

La domanda era se c'era un'altra opzione nel Concurrency Runtime che fornisce funzionalità di coda di blocco perché concurrent_queue non ce l'ha e ce n'è una in VS2010.

Il commento di Arch è ovviamente completamente corretto, il blocco delle code e le code di sblocco sono casi di utilizzo separati ed è per questo che sono diversi in VS2010 e in TBB.

In VS2010 è possibile utilizzare la classe template unbounded_buffer, i metodi appropriati sono chiamati enqueue e dequeue.

-Rick