Come facilitare l'accesso sicuro ai thread a un ampio set di variabili condivise?

4

Ho 2 set - input e output - di 70 variabili intere a 32 bit e 70 bool (140 vars del tutto). Questi devono essere accessibili e modificati da 3 thread. Qual è un modello di progettazione appropriato per facilitare l'accesso in lettura-scrittura sicuro a thread a ciascuna di queste 140 variabili senza bloccarle tutte in un unico mutex (che mi aspetto si tradurrà in prestazioni inadeguate)?

Alcuni dettagli sui requisiti di rendimento:

  • Il thread 1 ("CAN Serial Communication") riceve pacchetti da sensori hardware ogni 1ms che contengono il valore aggiornato per una delle 70 variabili condivise di input; il thread aggiorna la variabile con quel valore. Inoltre, ogni Thread 5ms deve fare una copia di tutte le 70 variabili di output.

  • Il thread 2 ("Controller") crea una copia di tutte le variabili di input ogni 10 ms, oltre a sovrascrivere tutte le variabili di output.

  • Il thread 3 ("GUI") esegue una copia di tutte le variabili di input e di output ogni 500ms.

  • Il sistema funziona su un ARM Cortex-A8 600Mhz.

Una soluzione è creare un blocco mutex per ognuna delle 140 variabili, ma questo sembra un trucco. Vorrei quindi avvolgere le variabili in una classe con 140 getter e setter, che sembra anche brutto.

Una nota a margine su std::atomic :

L'altra alternativa è std::atomic . Ma penso che sia una funzionalità avanzata e complicata, per esempio mi è stato detto su IRC che il seguente frammento di esempio non è thread-safe, nonostante l'aspetto intuitivo di come dovrebbe essere:

typedef struct MyStruct {
        std::atomic<int> a;
        std::atomic<int> b;
}

std::atomic<MyStruct> atomic_struct;
atomic_struct.a = 1;
atomic_struct.b = 2;

// Make a copy of 'atomic_struct'
Mystruct normal_struct;
normal_struct = atomic_struct;

// Edit the values of the copied struct and copy the changes back to the 'atomic_struct'.
normal_struct.a = 100;
normal_struct.b = 200;
atomic_struct = normal_struct;
    
posta DBedrenko 20.05.2016 - 11:43
fonte

2 risposte

4

Commenti trasformati in una risposta:

Hai ragione a preoccuparti delle prestazioni con il blocco di tutto sotto un mutex, ma la soluzione migliore è assicurarti che ci sia il minimo possibile nel lucchetto.

Il thread 1 dovrebbe avere il valore e l'indice pronto e in realtà sta solo facendo una singola scrittura. La discussione 2 funzionerebbe su un'istanza locale non condivisa della classe e la scambierà con quella condivisa. Thread 3 ha anche un'istanza locale non condivisa che copia la condivisione in ogni aggiornamento

    
risposta data 20.05.2016 - 12:11
fonte
2

Nel tuo caso particolare (tutte le variabili essendo scalari, cioè integrale o booleano) potresti prendere in considerazione l'utilizzo di atomico strutture di C ++ 11. Hai bisogno di un recente compilatore GCC o Clang.

Quindi useresti std::atomic_bool e ad es. std::atomic_int ecc ... per i tipi di queste variabili e usa atomic_load & atomic_store . Un utilizzo semplice sarebbe quello di utilizzare sistematicamente atomic_load & atomic_store per ogni accesso (o assegnazione) a queste variabili atomiche.

Per le operazioni che riguardano l'intero set di variabili (ad esempio, creando una copia di tutte loro), avrai bisogno di un mutex globale.

Ovviamente c'è una penalità legata alle prestazioni, ma probabilmente è molto più bassa rispetto all'utilizzo di mutex espliciti (à la std: : mutex ). Non conosco esattamente la tua piattaforma, ma immagino che ogni accesso sarebbe forse qualche decina di volte più lento rispetto ai normali dati non atomici. Devi fare un punto di riferimento. La maggior parte delle implementazioni mutex (almeno su Linux) utilizzano l'equivalente della macchina di scalari atomici accoppiati a macchine più complesse come futex (7) (ed è per questo che in pratica i mutex sono più lenti dell'atomica).

In alternativa, considera il raggruppamento delle variabili insieme (in modo significativo) e un mutex che controlla un piccolo sottoinsieme (ad esempio mezza dozzina) di variabili.

    
risposta data 20.05.2016 - 12:07
fonte

Leggi altre domande sui tag