[Python] pensierino della sera sul multiprocessing, sul cambiare le carte in tavola, sui seg-fault e sulla memoria già condivisa,

enrico franchi enrico.franchi a gmail.com
Lun 30 Maggio 2016 16:08:13 CEST


2016-05-27 22:52 GMT+01:00 alessandro medici <alexxandro.medici a gmail.com>:

>
>
> 1° è l'uso estensivo dei dizionari creati nel processo padre ed aggiornati
> dai processo figlio, sia nelle voci che nel contenuto. Un giro rapido e,
> stupore, non solo i dizionari, ma anche liste. L'unica cosa che non ho
> visto fare è applicare il metodo __del__, cosa comprensibile, peraltro,
> almeno per la salute mentale del memory manager.
>

E, come si diceva, se stai usando massicciamente dizionari in shared memory
stai sbagliando piu' che qualcosa. Tipo hai probabilmente sbagliato
completamente il linguaggio e/o l'architettura.


> Ecco: basterebbe FORSE creare un'altro dizionario delle voci che
> andrebbero cancellate e poi, magari, farlo dopo?
> Ok, 1° compito prima delle vacanze: Ma i dizionari sono pressoché gli
> unici oggetti composti che si possono aggiornare in multiprocess?
>

???

Ma ti e' chiaro che il 95% della gente che usa multiprocessing lo fa in
modo completamente diverso da come lo fai tu? Cioe' io ho visto delle gran
chiamate a Process (che ti lancia un nuovo processo che esegue una funzione
di tua scelta con argomenti di tua scelta. Dopo di che se devi continuare a
comunicare metterai in piedi qualche forma di IPC sensata fra processi. E
ancora di piu' la gente usa Pool (che e' una cattiva idea sotto tanti punti
di vista), ma formalmente ti da il concetto di "pool di worker" cui
sottometti task che loro eseguono e tanti saluti.

Poi e' chiaro, sei liberissimo di progettare architetture come si faceva
prima che ci si rendesse conto che non e' una buona idea. Ma non ti stupire
se la gente ti dice che non e' una buona idea. Appunto perche' negli ultimi
20 anni ci si e' sempre piu' reso conto che *non* e' una buona idea.

Aggiungo... perfino nel mondo Java, che era l'impero della memoria
condivisa, la gente che scrive Java per davvero si e' spostata altrove.
Buona parte delle feature dei nuovi Java sono in favore di avere pool di
task che fanno cose, eventualmente con costrutti relativamente funzionali
come i futures. Tipicamente cerchi di limitare al massimo l'uso di lock e
di memoria condivisa perche' *non* scalano.

E quindi hai i vari bus ad eventi dentro Guava/Guice, hai vari sistemi ad
attori (tipo Akka, che viene da scala, ma insomma... si usa anche in Java).
Hai Scala e Clojure (entrambi sulla JVM) ed entrambi cercano di promuovere
un diverso modo di fare concorrenza.

Tra l'altro in Python quando metti su un'architettura spesso passi da
Celery o magari da rq... e ti muovi proprio nella direzione di avere task
che vengono fatti girare su pool di worker. E il motivo per cui lo si fa e'
che multiprocessing non ti da molto a livello di architettura; e' comodo da
usare per cose semplici, ma poi gli manca parecchia colla per andare in
produzione.


>
> La 2° viene dall'altra idea:
> Mi era venuto subito in mente quando lessi l'articolo che postai qualche
> giorno addietro, quel qualcosa sul cambiare le ruote alla bici mentre si
> pedala:
> http://mathamy.com/python-wats-mutable-default-arguments.html
> cosa succederebbe se cambiassi le variabili di default di una classe o di
> un metodo mentre la loro progenie è occupata in un processo? Magari in una
> ABC genitore?
>
> Forse nulla. Forse dipenderà dal metodo con cui si lanceranno i processi? (
> https://docs.python.org/3.5/library/multiprocessing.html#the-spawn-and-forkserver-start-methods
> usa inherits ma non chiarisce se intende 'copiare' o 'linkare')
>
> Forse salto in aria :)
>
> E poi vedo Enrico leggermi, e che già chiede per me a viva voce un TSO,
> pensare ancora più a ragione un 'ma chi me lo fa fare'? Eddai: forza e
> coraggio Enrico, ormai sono sulla via della tomba, che quella con la r in
> più ormai la vedo raramente :-(
>

Diciamo cosi'... tu consisti ad insistere su sta cosa della memoria
condivisa come se fosse un problema. Non e' un problema. Tanto per dirne
una, se vai a memoria condivisa non riuscirai *mai* a fare scalare la tua
applicazione per davvero. Per cui normalmente la gente nel 2016 *non* usa
memoria condivisa come si faceva negli anni 90. Se hai memoria condivisa,
vuoi che sia estremamente locale per determinate cose e che tipicamente non
sia come comunicano i pezzi della tua applicazione (per mille motivi). Non
si scrive cosi' il codice.

Come dicevo altrove... ci sono eccezioni. Per esempio se stai scrivendo una
pipeline di processamento audio dentro il kernel. Ma in questo caso non
ragioni in termini di processi e non lo fai in Python.

Se stai lavorando in Python su una cosa nella quale le performance sono
critiche:
1. di solito si parla di performance di I/O
2. di solito non puoi permetterti di non scalare orizzontalmente.

E in questi casi la soluzione (1) non passa da multiprocessing (se non,
eventualmente, tangentalmente) e (2) non vuoi usare la memoria condivisa.


>
> 17.2.1.5. Sharing state between processes¶
> <https://docs.python.org/3.5/library/multiprocessing.html#sharing-state-between-processes>
> nella pagina che cito poco sopra e poi si dia un ctrl-f su shared memory.
>


Puoi essere piu' specifico? Tipo dal fatto che inizia per 17 (e dal link)
inferisco che parli di Python 3.5...
 Ma poi non capisco dove parlano di seg fault.



Evidentemente il timore del seg-fault non li ha fermati. Ed, a me, averla
> organizzata come array mi va benissimo: il mappare dati in modo diverso nel
> Cobol era una delle cose più divertenti da fare nell'epoca di quando ero un
> ragazzino. Almeno quando ero vestito.
> (Al riguardo dei vestiti il BDFL ed io il  abbiamo le stesse idee. E anche
> la stessa età :-(  :)
>

E non e' manco vero che e' (solo) organizzata ad array.

Ma scusa... piu' di:

"""

As mentioned above, when doing concurrent programming it is usually best to
avoid using shared state as far as possible. This is particularly true when
using multiple processes.

However, if you really do need to use some shared data then multiprocessing
<https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing>
provides
a couple of ways of doing so.
"""

Cioe' qua sono i primi paragrafi dove ti introduce la feature.
Essenzialmente prima ancora di dirti cosa puoi fare e come, ti dice di non
usare questa feature. Piu' di cosi'...

E poi leggi la documentazione... fanno tutto a botte di synchronized. E 30
anni di Java ci hanno insegnato chiaramente che partire da primitive dove
tutto e' sincroniuzzato non avra' performance accettabili (anche perche'
Java almeno tenta di capire quali synchronized non sono necessari e non
generare codice... ma Python non puo' farlo e se li deve pagare tutti).

Cioe'... la feature e' li. Magari qualcuno riesce anche a farci qualcosa di
utile; ma dovrebbe essere tipo l'ultima strada da percorrere.

-- 
.
..: -enrico-
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.python.it/pipermail/python/attachments/20160530/e956e64b/attachment.html>


Maggiori informazioni sulla lista Python