Come posso migliorare il mio comportamento in tempo reale in App multi-threaded con pthreads e variabili di condizione?

StackOverflow https://stackoverflow.com/questions/2894191

Domanda

Ho un'applicazione multi-threaded che utilizza pthreads. Ho un mutex () di blocco e condizioni variabili (). Ci sono due thread, un thread sta producendo dati per il secondo filo, un lavoratore, che cerca di elaborare i dati prodotti in una vera e propria moda tempo così che un mandrino viene elaborato come vicino al trascorrere di un periodo di tempo determinato come possibile.

Questo funziona abbastanza bene, tuttavia, di tanto in tanto quando i rilasci filo produttore la condizione su cui si attende il lavoratore, un ritardo fino a quasi un intero secondo si vede prima che il thread di lavoro ottiene di nuovo il controllo e l'esegue.

Lo so perché a destra prima del rilascio alla produzione la condizione su cui è in attesa il lavoratore, che fa un mandrino di elaborazione per il lavoratore se è il momento di elaborare un altro mandrino, quindi immediatamente dopo aver ricevuto la condizione nel thread di lavoro, lo fa anche un mandrino di elaborazione se è il momento di elaborare un altro mandrino.

In questo caso poi, sto vedendo che io sono in ritardo l'elaborazione del mandrino molte volte. Mi piacerebbe eliminare questo efficienza perduto e fare quello che posso per mantenere i mandrini ticchettio lontano il più vicino al possibile la frequenza desiderata.

C'è qualcosa che posso fare per ridurre il ritardo tra la condizione di rilascio da parte del produttore e la rilevazione che tale condizione viene rilasciato in modo tale che il lavoratore riprende il trattamento? Ad esempio, sarebbe aiutare per il produttore alla chiamata qualcosa per costringere se stessa di essere contesto disinserito?

Linea di fondo è il lavoratore deve aspettare ogni volta che si chiede al produttore di creare lavoro per se stessa in modo che il produttore può muck con strutture di dati del lavoratore prima di dire il lavoratore è pronto per l'esecuzione in parallelo di nuovo. Questo periodo di accesso esclusivo da parte del produttore è destinata ad essere breve, ma durante questo periodo, sto anche controllando per il lavoro in tempo reale per essere fatto dal produttore per conto del lavoratore, mentre il produttore ha accesso esclusivo. In qualche modo la mia mano fuori di nuovo a correre nei risultati di nuovo parallele in notevole ritardo di tanto in tanto che vorrei evitare. Si prega di suggerire come questo potrebbe essere meglio raggiunto.

È stato utile?

Soluzione

ho potuto suggerire il seguente schema. In genere, la stessa tecnica potrebbe essere utilizzata, ad esempio, quando prebuffering cornici in alcuni rendering in tempo reale, o qualcosa di simile.

In primo luogo, è evidente che l'approccio che si descrive nel suo messaggio sarebbe solo efficace se entrambi le discussioni che sono caricati altrettanto (o quasi ugualmente) per tutto il tempo. In caso contrario, il multi-threading sarebbe effettivamente beneficiare nella vostra situazione.

Ora, pensiamo a un modello di filo che sarebbe ottimale per il vostro problema. Supponiamo di avere un yielding e un filetto processing. Prima di loro prepara quantità di dati da elaborare, la seconda rende elaborazione e memorizza il risultato dell'elaborazione da qualche parte (in realtà non importante).

Il modo più efficace per rendere questi fili lavorano insieme è il meccanismo cedevole corretta. Il tuo filo yielding deve semplicemente aggiungere dati ad alcune buffer condiviso e non dovrebbe in realtà cura di ciò che sarebbe accaduto con quei dati. E, beh, il buffer potrebbe essere implementato come un semplice coda FIFO. Ciò significa che il filo yielding dovrebbe preparare i dati di processo e di effettuare una chiamata PUSH alla coda:

X = PREPARE_DATA()
BUFFER.LOCK()
BUFFER.PUSH(X)
BUFFER.UNLOCK()

Ora, il filo processing. E 'il comportamento dovrebbe essere descritto in questo modo (probabilmente si dovrebbe aggiungere un po' di ritardo artificiale come SLEEP(X) tra le chiamate a EMPTY)

IF !EMPTY(BUFFER) PROCESS(BUFFER.TOP)

Il momento importante qui è quello che dovrebbe essere il vostro thread di elaborazione che fare con dati elaborati. I mezzi approccio più ovvio che fanno una chiamata POP dopo che i dati sono trattati, ma probabilmente si vorranno venire con qualche idea migliore. In ogni caso, nella mia variante di questo apparirebbe come

// After data is processed
BUFFER.LOCK()
BUFFER.POP()
BUFFER.UNLOCK()

Si noti che le operazioni in yielding e processing discussioni blocco non dovrebbe in realtà avere un impatto le prestazioni, perché sono chiamati solo una volta per ogni blocco di dati.


Ora, la parte interessante. Come ho scritto all'inizio, questo approccio potrebbe essere efficace solo se le discussioni si comportano un po 'lo stesso in termini di CPU / utilizzo delle risorse. C'è un modo per rendere queste soluzioni filettatura efficace anche se questa condizione non è sempre vero e questioni su alcune altre condizioni di esecuzione.

In questo modo significa creare un altro thread che si chiama filo controller. Questo thread farebbe che confronta il tempo che ogni usi filo di elaborare un blocco di dati e bilanciare le priorità di thread di conseguenza. In realtà, non abbiamo a "confrontare il tempo" , il filo controller potrebbe semplicemente lavorare nel modo come:

IF BUFFER.SIZE() > T
   DECREASE_PRIORITY(YIELDING_THREAD)
   INCREASE_PRIORITY(PROCESSING_THREAD)

Naturalmente, è possibile implementare alcune euristiche meglio qui, ma l'approccio con il filo controller dovrebbe essere chiaro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top