Valutazione degli approcci concomitanti alla progettazione di applicazioni su Linux

5

Lavorando su hardware relativamente a bassa velocità, ho bisogno di catturare un'istantanea di un flusso di dati in rapida evoluzione e quindi post-elaborare i dati dell'istantanea e salvarli su disco.

Ho bisogno di aiuto per progettare l'approccio generale dato i vincoli di elaborazione dall'hardware.

La fase snapshot deve essere completata in modo relativamente istantaneo, perché blocca il flusso di dati mentre esegue l'acquisizione. Credo di voler eseguire questo come un processo separato, o almeno come thread stand-alone. Questa fase deve essere data la priorità per l'elaborazione e l'accesso alle risorse.

La fase post-elaborazione si basa su librerie esterne che non utilizzano un modello di chiamata di funzione / API ripetuta-iterazione. Sarebbe in grado di limitare la velocità di chiamata di - invece, una singola funzione la chiamata esegue l'intera operazione.

Tuttavia, non mi interessa quando finiscono queste attività di post-elaborazione, e preferirei che questa routine venisse eseguita in modo tale da funzionare per CPU / IO molto piccole durante il funzionamento. Il mio pensiero è che ciò incoraggerebbe gli eventi futuri dello snapshot per completare con un minimo di latenza. La post-elaborazione impiega solo pochi secondi per essere completata, ma la priorità è maggiore della latenza dello snapshot rispetto alla velocità di post-elaborazione.

Tenendo conto di tutti questi requisiti, per me è logico eseguire entrambe queste azioni come attività concorrenti separate e dire al kernel che l'attività di snapshot ha una priorità estremamente elevata e che l'attività post-processo ha una priorità estremamente bassa .

Generalmente dico task qui, e ho detto "concurrent" nel titolo, perché non sono sicuro se voglio usare processi separati per questo, o implementare qualche forma di multi-threading .
Ho solo una piccola esperienza con fork() e simili, e non ho esperienza con il threading, quindi ho alcune domande su come / dove dovrei iniziare:

  • Quale metodo sarebbe preferibile - thread o processi separati? L'utilizzo dei thread semplifica la condivisione dell'accesso alla memoria tra le due attività?

  • Posso impostare la pianificazione del kernel / priorità IO quando utilizzo i thread? O mi preoccupo troppo dell'impostazione della priorità del kernel a questo punto?

  • Per mantenere il processo di snapshot veloce, sarebbe ideale che l'attività di snapshot lasci semplicemente i dati da elaborare seduti in memoria affinché l'attività di post-processo venga ripresa ed eseguita, quindi l'attività di istantanea è immediatamente chiara e aspettando il prossimo evento. Questo sembra essere meglio affrontato con un approccio di accodamento, ma non so se ci sono approcci che forniscono altri vantaggi.

Se stavo usando fork() , potrei semplicemente lasciare i dati non elaborati in una pipe() per l'attività post-processo da ripulire dopo. Sono sicuro che il pipe non si riempirà e bloccerà il processo di snapshot.
Non sono sicuro di cosa posso fare con il threading. Potrei eventualmente allocare memoria dal thread di snapshot; condividere i puntatori tramite IPC; allora free() i dati dal thread post-processo? Guadagno velocità di elaborazione o altri benefici adottando questo approccio?

Per aiutare a focalizzare la mia domanda, ho due vasti percorsi che sto considerando.

  1. Due processi separati che utilizzano la funzionalità pipe() del SO per fornire comunicazione tra di loro.

  2. Un processo multi-thread che utilizza IPC o altri meccanismi di comunicazione.

Devo essere in grado di assegnare la priorità a un'attività sull'altra e probabilmente su altri processi in esecuzione sul sistema. Ho dei limiti di tempo per l'esecuzione di una delle attività, ma non mi interessa il tempo di esecuzione per la seconda attività.

I miei due percorsi potenziali sono equivalenti, oppure c'è un approccio preferito dato i miei vincoli? O c'è un terzo approccio che è meglio di quei due?

    
posta i336_ 07.11.2014 - 12:05
fonte

1 risposta

1

Which method would be preferable - threading or separate processes? Does utilizing threads simplify sharing memory access between the two tasks?

I thread semplificano (e migliorano notevolmente le prestazioni) dell'accesso alla memoria condivisa. Si useranno i processi se si vuole essere certi che nel caso in cui una delle attività si blocchi, l'altra attività rimane inalterata, ma nel proprio scenario particolare, questo non ti comprerebbe nulla: se l'attività dell'istantanea si blocca, l'attività di post-elaborazione non ha lavoro da fare, quindi è un punto controverso se sopravvive all'incidente. D'altra parte, se l'attività di post-elaborazione si arresta, i dati grezzi ottenuti dall'attività di snapshot andranno persi. Quindi, a meno che non si sia disposti a bufferizzare temporaneamente i dati grezzi sul disco, non sono necessari due processi; due thread funzioneranno perfettamente.

Can I set kernel scheduling/IO priority when using threads? Or am I worrying too much about setting kernel priority at this point?

Sì, può farlo con i thread. E probabilmente non dovrete nemmeno andare agli estremi: l'attività di istantanea deve avere solo una priorità leggermente più alta rispetto all'attività di post-elaborazione per assicurarsi che l'attività di post-elaborazione non preveda mai l'attività di istantanea. Tuttavia, se si desidera assicurarsi che nient'altro sulla macchina ritardi l'attività di snapshot, utilizzare la priorità in tempo reale (massima) per l'attività di istantanea e la priorità normale per l'attività di post-elaborazione.

To keep the snapshot process fast, it would be ideal for the snapshot task to simply leave data to process sitting in memory for the post-process task to pick up and run with, so the snapshot task is immediately clear and waiting for the next event. This seems to be best addressed with a queuing approach, but I don't know if there are approaches that provide other advantages.

Sì, l'accodamento funzionerà bene. Potrebbe essere utile non utilizzare una coda di dati, ma una coda di puntatori ai blocchi di memoria contenenti dati, in modo da ridurre al minimo la copia dei dati.

Ora, tutto ciò che è stato detto, dovresti esaminare la possibilità di usare il disco come un buffer tra le tue due attività, perché in questo modo, se dovessi interrompere temporaneamente l'attività di post-elaborazione, non perderai il dati generati dall'attività di snapshot mentre l'attività di post-elaborazione viene interrotta. Ciò a sua volta consentirà di utilizzare anche processi separati per le due attività, che mantengono le cose pulite e fornisce ulteriore sicurezza: se una delle attività si blocca, l'altra può continuare a funzionare. Se l'attività di post-elaborazione si arresta in modo anomalo, l'attività di snapshot può continuare a generare dati grezzi che non verranno persi perché vengono mantenuti e se l'attività di snapshot si arresta in modo anomalo, l'attività di post-elaborazione potrebbe disporre di un backlog di dati non elaborati precedentemente mantenuti per mantenere stesso occupato con.

Se sei sicuro di non aver mai bisogno di persistere dati grezzi sul disco, allora un altro problema diventa evidente: né multi-threading né multi-tasking ti fanno acquisti!

Come vedete, l'attività di post-elaborazione non sarà mai consentita per anticipare l'attività di istantanea, ma dovrà sempre consumare dati grezzi alla stessa velocità o maggiore rispetto alla velocità con cui l'attività di snapshot produce dati grezzi, o altrimenti i dati andranno persi. Quindi, questo significa che puoi avere entrambe le "attività" in modo serrato, nella stessa discussione : prima viene richiamata l'attività di snapshot per generare i dati, quindi il post- l'attività di elaborazione viene invocata per elaborare i dati, quindi è possibile o meno attendere fino al momento in cui è necessario scattare un'altra istantanea e ripetere.

    
risposta data 09.12.2015 - 08:02
fonte

Leggi altre domande sui tag