Domanda

Ho visto una domanda sul perché "polling è cattivo". In termini di riduzione della quantità di tempo processore utilizzato da un thread, sarebbe meglio fare un giro attesa (cioè sondaggio per un cambiamento richiesto in un ciclo while) o attendere su un oggetto kernel (ad esempio un oggetto evento kernel in finestre) ?

Per contesto, si supponga che il codice sarebbe richiesto per funzionare su qualsiasi tipo di processore, single core, hyperthreaded, multicore, ecc assume inoltre che un filo che polling o attendere non può continuare finché il risultato è soddisfacente polling se interrogato, invece di aspettare. Infine, il tempo tra quando un thread inizia attesa (o polling) e quando la condizione è soddisfatta potenzialmente possono variare da un tempo molto breve per un lungo tempo.

Dal momento che il sistema operativo è probabile che in modo più efficiente "sondaggio" in caso di "attesa", non voglio vedere la "in attesa solo significa che qualcun altro fa il polling" argomento, questa è una notizia vecchia, e non è necessariamente accurato al 100%.

È stato utile?

Soluzione

A condizione che il sistema operativo ha ragionevoli implementazioni di questo tipo di primitive di concorrenza, è sicuramente meglio aspettare su un oggetto del kernel.

Tra l'altro, questo permette al sistema operativo sa di non pianificare il thread in questione per la porzione di tempo supplementari fino a quando l'oggetto da attese per la si trova nello stato appropriato. In caso contrario, si ha un filo che viene costantemente ottenendo riprogrammato, contesto-acceso-to, e poi correre per un po '.

È espressamente chiesto di ridurre al minimo il tempo di processore per un filo: in questo esempio, il filo di blocco su un oggetto di kernel userebbe ZERO tempo; il thread di polling sarebbe utilizzare tutti i tipi di tempo.

Inoltre, il "qualcun altro è polling" l'argomento non deve essere vero. Quando un oggetto kernel entra nello stato appropriato, il kernel può guardare per vedere in quell'istante che thread attendono quell'oggetto ... e quindi pianificare uno o più di essi per l'esecuzione. Non c'è bisogno per il kernel (o chiunque altro) per prelevare nulla in questo caso.

Altri suggerimenti

L'attesa è la via "più bello" a comportarsi. Quando si è in attesa su un kernel oggetto il thread non sarà concesso alcun tempo di CPU, come è noto dallo scheduler che non c'è lavoro pronto. Il tuo thread è solo andare a essere dato il tempo di CPU quando è attesa la condizione è soddisfatta. Il che significa che non sarà monopolizzavano le risorse della CPU inutilmente.

Credo che un punto che non è stato ancora sollevato è che se il sistema operativo ha un sacco di lavoro da fare, bloccando yeilds tuo thread a un altro processo. Se tutti i processi utilizzano le primitive di blocco dove dovrebbero (come attese del kernel, file / rete IO ecc) si sta dando al kernel ulteriori informazioni per scegliere quali le discussioni dovrebbero funzionare. Come tale, essa farà più lavoro nello stesso lasso di tempo. Se l'applicazione potrebbe fare qualcosa di utile durante l'attesa per il file da aprire o il pacchetto per arrivare poi yeilding aiuterà anche sei proprio app.

In attesa fa coinvolgere più risorse e indica un cambio di contesto aggiuntivo. In effetti, alcune primitive di sincronizzazione come Monitor CLR e sezioni critiche Win32 utilizzano un protocollo di blocco a due fasi - una certa rotazione di attesa è fatto ribalta in realtà facendo una vera e propria attesa

.

I immaginare di fare la cosa a due fasi sarebbe molto difficile, e comporterebbe un sacco di test e ricerche. Quindi, se non avete il tempo e le risorse, il bastone per le primitive finestre ... hanno già fatto la ricerca per voi.

Ci sono solo pochi posti, di solito entro le cose di basso livello del sistema operativo (interrompere driver gestori / del dispositivo) in cui spin-attesa ha senso / è necessaria. applicazioni generiche sono sempre meglio aspettare su alcune primitive di sincronizzazione come mutex / variabili condizionali / semafori.

Sono d'accordo con Darksquid, se il sistema operativo ha primitive concorrenza decenti allora non dovrebbe essere necessario eseguire il polling. polling di solito entra in essa la propria su sistemi in tempo reale o hardware limitato che non dispone di un sistema operativo, allora avete bisogno di polling, perché si potrebbe non avere la possibilità di attendere (), ma anche perché ti dà il controllo a grana fine su esattamente quanto tempo si vuole aspettare in un particolare stato, invece di essere alla mercé dello scheduler.

In attesa (blocco) è quasi sempre la scelta migliore ( "migliore", nel senso di fare un uso efficiente delle risorse di elaborazione e riducendo al minimo l'impatto di altro codice in esecuzione sullo stesso sistema). Le eccezioni principali sono:

  1. Quando la durata di polling previsto è piccola (simile in grandezza al costo della chiamata di sistema di blocco).
  2. Per lo più in sistemi embedded, quando la CPU è dedicato a svolgere un compito specifico e non v'è alcun vantaggio di avere l'inattività della CPU (ad esempio alcuni router software costruiti negli anni '90 utilizzato questo approccio).

Polling è generalmente utilizzato entro kernel OS di implementare sistemi di blocco chiamate -. Invece, eventi (allarmi, timer, azioni su mutex) comportare un processo bloccato o filo compiuti eseguibile

Ci sono quattro approcci di base si potrebbe prendere:

  1. uso di alcune OS in attesa primitiva aspettare fino a quando si verifica l'evento
  2. uso di alcune timer OS primitivo di controllare ad un certo tasso definito se l'evento si è ancora verificato
  3. controllare ripetutamente se si è verificato l'evento, ma utilizzare un sistema operativo primitivo a cedere una fetta di tempo per una durata arbitrario e sconosciuto qualsiasi momento che non ha.
  4. controllare ripetutamente se si è verificato l'evento, senza cedimenti la CPU se non ha.

Quando # 1 è pratico, è spesso l'approccio migliore a meno che non ritardare la propria risposta all'evento potrebbe essere utile. Ad esempio, se si aspetta di ricevere una grande quantità di dati porta seriale nel corso di diversi secondi, e se l'elaborazione 100ms dati dopo l'invio sarà altrettanto buono come elaborarlo istantaneamente, polling periodico utilizzando uno di questi ultimi due approcci potrebbe essere migliore di creazione di un evento di "dati ricevuti".

Approccio # 3 è piuttosto grezzo, ma può in molti casi essere un buon compromesso. Sarà spesso sprecare più tempo di CPU e risorse di quanto si avvicinerebbe 1 #, ma sarà in molti casi essere più semplice da implementare e lo spreco di risorse in molti casi essere abbastanza piccolo da non avere importanza.

Approccio # 2 è spesso più complicato di 3 #, ma ha il vantaggio di essere in grado di gestire molte risorse con un unico timer e non thread dedicato.

Approccio # 4 volte è necessario in sistemi embedded, ma è in genere molto male se non si è direttamente all'hardware polling e la volontà di non avere nulla di utile da fare fino a quando si verifica l'evento in questione. In molte circostanze, non sarà possibile per la condizione di essere aspettato upon a verificarsi finché il filo aspettare che produce la CPU. Cedendo la CPU come nel metodo # 3 sarà infatti consentire al thread in attesa di vedere l'evento prima di quanto sarebbe monopolizzavano esso.

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