44

Erlang è noto per essere in grado di supportare MOLTI processi leggeri; può farlo perché non si tratta di processi nel senso tradizionale, o addirittura di thread come in P-threads, ma si inserisce interamente nello spazio utente.Come fare, se non del tutto, mappare i processi di Erlang ai thread del kernel?

Questo è buono e buono (in realtà fantastico). Ma in che modo i thread di Erlang vengono eseguiti in parallelo in un ambiente multicore/multiprocessore? Sicuramente devono essere mappati in qualche modo ai thread del kernel per poter essere eseguiti su core separati?

Supponendo che sia così, come è fatto? Molti processi leggeri sono mappati su un singolo thread del kernel?

Oppure c'è un altro modo per aggirare questo problema?

risposta

60

risposta dipende dalla macchina virtuale che viene utilizzato:

1) non SMP: C'è uno scheduler (filo OS), che esegue tutti i processi di Erlang, tratto dal pool di processi eseguibili (cioè quelli che non sono bloccata esempio receive)

2) SMP: Risultano K schedulatori (fili OS, K è di solito un certo numero di nuclei di CPU), che esegue Erlang processi dalla coda di processo condivisa . È una semplice coda FIFO (con blocchi per consentire l'accesso simultaneo da più thread del sistema operativo).

3) SMP in R13B e successivi: Ci saranno K schedulatori (come prima) che esegue processi Erlang da più code processo. Ogni schedulatore ha la propria coda, quindi verrà aggiunta la logica di migrazione da uno schedulatore all'altro. Questa soluzione migliorerà le prestazioni evitando il blocco eccessivo nella coda dei processi condivisa.

Per ulteriori informazioni vedere this document preparato da Kenneth Lundin, Ericsson AB, per Conferenza Erlang User, Stoccolma, 13 novembre 2008.

1

Sto solo indovinando qui, ma immagino che ci sia un piccolo numero di thread, che prelevano i processi da un comune pool di processi per l'esecuzione. Una volta che un processo raggiunge un'operazione di blocco, il thread che lo esegue lo mette da parte e ne sceglie un altro. Quando un processo in esecuzione fa sì che un altro processo venga sbloccato, quel processo appena sbloccato viene inserito nel pool. Suppongo che un thread potrebbe anche interrompere l'esecuzione di un processo anche quando non è bloccato in determinati punti per servire altri processi.

+0

Sì, ho la sensazione che qualcosa di simile stia succedendo ... –

10

voglio ammend risposte precedenti.

Erlang, o meglio il sistema di runtime Erlang (erts), imposta automaticamente il numero di schedulatori (thread del sistema operativo) e il numero di code di attesa sul numero di elementi di elaborazione sulla piattaforma. Questo è il core del processore o il thread dell'hardware. È possibile modificare queste impostazioni in fase di runtime utilizzando:

erlang:system_flag(schedulers_online, NP) -> PrevNP 

I processi di Erlang non ha un'affinità a qualsiasi pianificatori ancora. La logica che bilancia i processi tra gli scheduler segue due regole. 1) Un programmatore affamato ruberà il lavoro da un altro schedulatore. 2) I percorsi di migrazione sono configurati per spingere i processi dagli scheduler con molti processi agli scheduler con meno lavoro.Questo viene fatto per assicurare equità nel conteggio delle riduzioni (tempo di esecuzione) per ogni processo.

Gli schedulatori tuttavia possono essere bloccati su elementi di elaborazione specifici. Questo non è fatto per impostazione predefinita. Per consentire erts fanno l'uso affinità scheduler-> nucleo:

erlang:system_flag(scheduler_bind_type, default_bind) -> PrevBind 

diversi altri tipi di legatura possono essere trovati nella documentazione. L'utilizzo dell'affinità può migliorare notevolmente le prestazioni in situazioni di carico pesante! Soprattutto in situazioni di contesa di blocco elevato. Inoltre, il kernel linux non può gestire i hyperthreads per non dire altro. Se hai hyperthreads sulla tua piattaforma dovresti davvero usare questa funzione in erlang.

1

Vorrei aggiungere un input a ciò che è stato descritto nella risposta accettata.

Erlang Scheduler è la parte essenziale di Erlang Runtime System e fornisce la propria astrazione e implementazione della concezione di processi leggeri in cima ai thread del sistema operativo.

Ciascun programma di pianificazione viene eseguito all'interno di un singolo thread del sistema operativo. Normalmente, ci sono tanti programmatori come CPU (core) sull'hardware (è configurabile e naturalmente non porta molto valore quando il numero di scheduler supera quelli dei core dell'hardware). Il sistema potrebbe anche essere configurato in modo che lo scheduler non salti tra i thread del sistema operativo.

Ora, quando viene creato il processo di Erlang è del tutto la responsabilità del ERTS e di pianificazione per la gestione del ciclo di vita e il consumo di risorse, nonché la sua impronta di memoria ecc

Uno dei dettagli di implementazione di base è che ogni processo ha un budget di tempo di 2000 riduzioni disponibili quando lo Scheduler preleva tale processo dalla coda di esecuzione. Ogni progresso nel sistema (anche I/O) è garantito per avere un budget di riduzioni. Questo è ciò che rende ERTS un sistema con il multitasking preemptive.

mi sento di raccomandare un grande post sul blog su questo argomento da Jesper Andersen Louis http://jlouisramblings.blogspot.com/2013/01/how-erlang-does-scheduling.html

Come la risposta breve: i processi di Erlang non sono le discussioni OS e non mappa a loro direttamente. Gli scheduler di Erlang sono ciò che viene eseguito sui thread del sistema operativo e forniscono un'implementazione intelligente di processi di Erlang a grana fine che nascondono questi dettagli dietro gli occhi del programmatore.