When I write...
l2 = [my_computation(x) for x in l]
..., I wonder if python is applying my_computation
to every x
using all cores of my CPU.
Il riferimento al linguaggio Python non proibisce esplicitamente né forza esplicitamente la valutazione asincrona, concorrente o parallela:
The comprehension consists of a single expression followed by at least one for
clause and zero or more for
or if
clauses. In this case, the elements of the new container are those that would be produced by considering each of the for
or if
clauses a block, nesting from left to right, and evaluating the expression to produce an element each time the innermost block is reached.
In effetti, come puoi vedere, in realtà non fornisce nessuna semantica di valutazione . Le due frasi sopra sono l'intera specificazione del comportamento di comprensione.
PEP202 - Comprensione delle liste è ancora meno utile.
If not, why ?
Come puoi vedere, è consentita un'implementazione, ma non è necessario per parallelizzare la comprensione degli elenchi. Tuttavia, parallelizzando è solo corretto se my_computation
è referenzialmente trasparente. E capire se è referenzialmente trasparente, equivale a risolvere il problema dell'arresto, ergo impossibile nel caso generale.
È, ovviamente, in casi specifici a volte possibile decidere la trasparenza referenziale, tuttavia, almeno su CPython, l'implementazione Python più popolare, che non sarà di aiuto: CPython non è in grado di eseguire comunque codice Python in parallelo.
Is there a simple way to make python parallelize list comprehensions?
Non che io sappia. Il loro comportamento è criptato nella lingua, non si traduce in messaggi inviati, quindi non c'è nulla che tu possa implementare o sovrascrivere per cambiare il loro comportamento.
Confrontalo con Scala o C #, ad esempio, che hanno una funzione correlata, che è definita come una semplice traduzione sintattica ai messaggi inviati e quindi può essere ignorata. Per esempio. in Scala, l'equivalente sarebbe
for (x ← l) yield myComputation(x)
e questo sarebbe tradotto in
l.map(x ⇒ myComputation(x))
Quindi, puoi cambiare il comportamento fornendo il tuo metodo map
, che è esattamente ciò che il Parallel Collections Framework viene fornito con Scala Standard Library fa.
Is this related to the behavior of map()
or not at all?
No. Se lo fosse, potresti cambiarlo fornendo il tuo metodo map
.
Il modulo concurrent.futures
nella libreria standard Python, ad esempio, fornisce il proprio metodo map
.