[PIPython] Python & Thread
Alex Martelli
aleaxit
Ven 19 Nov 2004 15:16:44 CET
On 2004 Mar 25, at 08:39, Stefano Maniero wrote:
> Salve a tutti, sono un neofita di python e provengo dal mondo java.
>
> Ho qualche dubbio sulla gestione dei thread: ho letto da più parti che
> python
> presenta alcuni limiti sulle performance dei thread legate al GIL. Per
> risolvere
L'implementazione Classic Python (con una sua macchina virtuale
dedicata) usa appunto un lock globale sull'interprete (GIL) che
impedisce che puro bytecode Python sia in esecuzione simultanea su
molteplici thread nello stesso interprete; l'esecuzione simultanea e`
limitata a codice C che rilasci il GIL (lo fanno ad esempio le librerie
standard Python per tutte le operazioni bloccanti di I/O, e le tipiche
estensioni a pesante impegno di CPU come, ad esempio, quelle per il
calcolo numerico -- ma non tutte [ad esempio non mi sono mai
preoccupato di rilasciare il GIL nell'estensione gmpy]). Questo non
"presenta limiti sulle performance dei thread" su tipici elaboratori
che dispongono di una singola CPU (anzi, riducendo le necessita` di
locking, puo` in piccola misura migliorare le performance), ma
impedisce ad un singolo processo multithreading, con un programma
scritto interamente in puro Python senza sostanziali componenti I/O
bound, senza sostanziale uso di estensioni che rilasciano il GIL, ed
eseguito in Classic Python, di occupare pienamente tutte le risorse di
calcolo di un singolo computer dotato di molteplici CPU
("multi-processor"). Ad esempio, passando da un computer
mono-processor (che mi pare nel mondo PC siano ben oltre il 90%) ad uno
con due processor, il suddetto programma puro Python non puo` far altro
che riempire interamente una singola CPU, lasciando all'altra solo
compiti come quello di eseguire il sistema operativo, tutti gli altri
processi in simultanea esecuzione, la rete, l'interfaccia utente, e
cosi` via.
Piu` incerto e` il discorso relativo alle nuove CPU Intel
"hyperthreading", che hanno un processore solo ma in un certo senso
permettono di "simularne" due (o almeno "uno e mezzo", che so) con
teorico e potenziale beneficio per programmi "freely threaded" (ma non
il suddetto ipotetico caso).
Di certo questo puo` essere un problema se il tuo scopo e` quello di
usare un singolo computer con tanti processori per eseguire, in
pratica, solamente un singolo programma alla volta e detto programma
rientra nella tipologia suindicata (CPU-intensive ma non usa le tipiche
estensioni Python in C, ecc, ecc). Non dubito che _almeno_ lo 0.01%
dei programmatori Python a tempo pieno si trovera` in situazioni simili
almeno una volta nel corso della sua vita, anche se in pratica di
solito, quella volta nella vita che mediamente gli capiteranno,
risolvera` usando estensioni C, o anche semplicemente una macchina
virtuale diversa (ad esempio, una qualsiasi macchina virtuale Java,
grazie all'implementazione "Jython" del linguaggio Python, ovvero
presto dotNet o Mono, grazie alla implementazione "IronPython" dello
stesso linguaggio Python recentemente intrapresa da Jim Hugunin, a suo
tempo inventore di Jython).
> questo problema sembra che l'unica soluzione sia il multiprocess,
> sbaglio? Il
Se il tuo scopo nella vita e` accelerare (nel senso della
_scalabiltia`_...) al massimo un ipotetico programma Python della
tipologia suddetta, e` probabile che strutturarlo come multi-processo
sia furbo -- ma lo stesso varrebbe per un programma in C, in Java, o
che altro, perche` una architettura multi-processo ti permette di
accedere a numeri di processori incomparabilmente maggiori nella
maggior parte dei casi, rispetto ai numeri risibili tipicamente
disponibili in SMP (e quindi ai thread usati in C o Java, o
naturalmente Jython, o quelli che rilasciano il GIL anche in Python
classico). In una casa media, ad esempio, e` difficile che ci siano
computer in SMP al di la` dei semplici Powermac G5, che comunque oltre
i due processori (a 64 bit) non vanno; Intel e AMD fanno spesso pagare
un premio eccessivo per qui modelli dei loro processori che hanno
potenzialita` di uso SMP, per non dire del costo esagerato della
componentistica di supporto rispetto all'eccellente rapporto
prezzo/prestazione ottenibile coi chipset limitati all'uso
monoprocessore, per cui mi pare che nessuno fra i principali fornitori
di computer per consumatori punti sulle architetture SMP con l'unica
eccezione, appunto, di Apple (che comunque non si spinge molto in la).
All'altro capo della gamma, se hai a disposizione un SMP da 4-8
processori dedicabile ai tuoi processi CPU-intensive, e` probabile che
potresti anche accedere a un cluster (beowulf o successori, su su sino
al gigantesco cluster/supercomputer della Virginia, che putacaso si
basa anch'esso su processori IBM G5 e architetture Apple) di decine, o
centinaia, o perche` no migliaia di processori, magari connessi fra
loro a velocita` da fare impallidire i bus interni di molte modeste
architetture SMP... ma, appunto, NON SMP, non sfruttabili da un singolo
processo multi-thread, solo da un programma strutturato in molteplici
processi.
Quindi, pur non essendo l'_unica_, l'architettura a molteplici processi
puo` essere spesso la strada _migliore_ per ottenere scalabilita`
esagerata, indipendentemente dal linguaggio di programmazione.
> GIL limita effettivamente l'usabilità dei thread? Esistono altre
> soluzioni?
L'usabilita` no di certo, solo potenzialmente le prestazioni nell'unico
caso suddetto su macchine SMP. Certo che esistono altre soluzioni. Ad
esempio nella stragrande maggioranza dei casi le prestazioni di tanti
programmi saranno I-O bound, non CPU-bound, e allora i thread non
ottimizzerebbero nulla anche senza GIL, la soluzione ottimale e` il
"multitasking cooperativo", pilotato dagli eventi, che offre ad esempio
Twisted.
> Quando e dove è conveniente utilizzare i thread in python rispetto al
> multiprocess? Il supporto dei thread in python è paragonabile al
> supporto
> offerto da java in termini di performance?
Mi sembra che possa esserci una certa confusione fra linguaggi e
macchine virtuali. Se scrivi un programma usando il linguaggio Python
puoi poi eseguirlo con la macchina virtuale dedicata classic python
(prestazioni generalmente migliori, ma GIL) o con una macchina virtuale
Java (niente GIL, magari altri difetti di prestazioni ad esempio
sull'I/O, dipende dal modello esatto di JVM e da dove gira) -- o presto
con una macchina virtuale dotNet o Mono, con vantaggi e svantaggi di
prestazioni in vari ambiti che saranno ovviamente ancora diversi.
Personalmente, quando scrivo un programma MT in Python lo strutturo
comunque con un pool di thread indipendenti che comunicano fra loro
rigorosamente via istanze di Queue. Oltre ad essere di gran lunga il
modo migliore per scrivere un programma MT dimostrabilmente corretto,
e` anche un'architettura che offre la massima facilita` di ri-codifica
come multi-processo (sostituendo le Queue con costrutti equivalenti
basati su socket o pipe). Il giorno che qualcuno mi regalera` un
cluster di qualche centinaiadi Athlon AMD-64 ne saro` certo felice.
Per ora, devo ammetterlo, possedendo al massimo un Powermac Dual G5,
non e` che mi serva a molto... anche perche` di solito i miei programmi
davvero pesanti sono I/O bound, come per il 99.9% dei comuni mortali (i
loro colli di bottiglia sono il database, la rete, i dischi, ...)
quindi per averli prestanti non li faccio MT, li faccio event-driven
(con Twisted, naturalmente!) e le prestazioni sono sorprendenti (il
giorno che non lo saranno abbastanza, senza riscrivere una riga del mio
codice, comincero` a giocare a fondo con le possibilta` che Twisted
offre per reactor specializzati, compresi quelli multi-thread e
multi-processo, per ottenere, potenzilamente, scalabilita` anche
superiore con lo stesso, identico codice applicativo).
Alex
More information about the Python
mailing list