<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2016-05-27 22:52 GMT+01:00 alessandro medici <span dir="ltr"><<a href="mailto:alexxandro.medici@gmail.com" target="_blank">alexxandro.medici@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div><br></div><div>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. </div></div></blockquote><div><br></div><div>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. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Ecco: basterebbe FORSE creare un'altro dizionario delle voci che andrebbero cancellate e poi, magari, farlo dopo?</div><div>Ok, 1° compito prima delle vacanze: Ma i dizionari sono pressoché gli unici oggetti composti che si possono aggiornare in multiprocess?<br></div></div></blockquote><div><br></div><div>???</div><div><br></div><div>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. </div><div><br></div><div>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.</div><div><br></div><div>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. </div><div><br></div><div>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. </div><div><br></div><div>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.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div>La 2° viene dall'altra idea:</div><div>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:</div><div><a href="http://mathamy.com/python-wats-mutable-default-arguments.html" style="font-size:12.8px" target="_blank">http://mathamy.com/python-wats-mutable-default-arguments.html</a><br></div><div>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? <br></div><div><br></div><div>Forse nulla. Forse dipenderà dal metodo con cui si lanceranno i processi? (<a href="https://docs.python.org/3.5/library/multiprocessing.html#the-spawn-and-forkserver-start-methods" target="_blank">https://docs.python.org/3.5/library/multiprocessing.html#the-spawn-and-forkserver-start-methods</a> usa inherits ma non chiarisce se intende 'copiare' o 'linkare')</div><div><br></div><div>Forse salto in aria :)</div><div><br></div><div>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 :-(</div></div></blockquote><div><br></div><div>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. </div><div><br></div><div>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. </div><div><br></div><div>Se stai lavorando in Python su una cosa nella quale le performance sono critiche:</div><div>1. di solito si parla di performance di I/O</div><div>2. di solito non puoi permetterti di non scalare orizzontalmente.</div><div><br></div><div>E in questi casi la soluzione (1) non passa da multiprocessing (se non, eventualmente, tangentalmente) e (2) non vuoi usare la memoria condivisa.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><h3 style="font-family:'Lucida Grande',Arial,sans-serif;font-weight:normal;color:rgb(26,26,26);border:0px;margin:0px;padding:0.3em 0px;font-size:22.4px">17.2.1.5. Sharing state between processes<a href="https://docs.python.org/3.5/library/multiprocessing.html#sharing-state-between-processes" title="Permalink to this headline" style="color:rgb(99,99,187);text-decoration:none;font-size:0.8em;padding:0px 4px" target="_blank">¶</a></h3><div>nella pagina che cito poco sopra e poi si dia un ctrl-f su shared memory.</div></div></blockquote><div><br></div><div><br></div><div>Puoi essere piu' specifico? Tipo dal fatto che inizia per 17 (e dal link) inferisco che parli di Python 3.5...</div><div> Ma poi non capisco dove parlano di seg fault.</div><div><br></div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>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.</div><div>(Al riguardo dei vestiti il BDFL ed io il  abbiamo le stesse idee. E anche la stessa età :-(  :)</div></div></blockquote></div><div class="gmail_extra"><br></div>E non e' manco vero che e' (solo) organizzata ad array.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Ma scusa... piu' di:</div><div class="gmail_extra"><br></div><div class="gmail_extra">"""</div><div class="gmail_extra"><p style="text-align:justify;line-height:22.4px;font-family:'Lucida Grande',Arial,sans-serif;font-size:16px">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.</p><p style="text-align:justify;line-height:22.4px;font-family:'Lucida Grande',Arial,sans-serif;font-size:16px">However, if you really do need to use some shared data then <a class="" href="https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing" title="multiprocessing: Process-based parallelism." style="color:rgb(99,99,187);text-decoration:none"><code class="" style="padding:0px 1px;font-size:15.44px;font-family:monospace,sans-serif;border-radius:3px;background-color:transparent"><span class="">multiprocessing</span></code></a> provides a couple of ways of doing so.</p></div><div class="gmail_extra">"""<br><br clear="all"><div>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'...</div><div><br></div><div>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).</div><div><br></div><div>Cioe'... la feature e' li. Magari qualcuno riesce anche a farci qualcosa di utile; ma dovrebbe essere tipo l'ultima strada da percorrere.</div><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"> .<br>..: -enrico-</div>
</div></div>