Il collo di bottiglia della velocità nel mio codice è un doppio stretto per gli elementi di loop su due array, xe y. Un trucco hpc standard per migliorare le prestazioni consiste nel fare il ciclo in blocchi in modo che i problemi di cache possano essere ridotti al minimo. Sto cercando di usare i generatori Python per eseguire lo chunking, ma la necessità di ricreare continuamente il generatore speso all'interno del ciclo for esterno sta uccidendo il mio runtime.Uso efficiente di generatori Python in uno stretto doppio per array loop su numpy
Domanda:
Esiste un algoritmo più intelligente per costruire il generatore appropriata per l'esecuzione di chunked doppio per i cicli?
illustrazione Calcestruzzo:
creerò due array fittizi, x, e y. Li terremo cortesi per l'illustrazione, ma in pratica si tratta di array numpy con elementi ~ 1e6.
x = np.array(['a', 'b', 'b', 'c', 'c', 'd'])
y = np.array(['e', 'f', 'f', 'g'])
Il doppio ingenua ciclo for sarebbe solo:
for xletter in x:
for yletter in y:
# algebraic manipulations on x & y
Ora cerchiamo di usare i generatori di fare questo ciclo in blocchi:
chunk_size = 3
xchunk_gen = (x[i: i+chunk_size] for i in range(0, len(x), chunk_size))
for xchunk in xchunk_gen:
ychunk_gen = (y[i: i+chunk_size] for i in range(0, len(y), chunk_size))
for ychunk in ychunk_gen:
for xletter in xchunk:
for yletter in ychunk:
# algebraic manipulations on x & y
Nota che, al fine di implementare una soluzione generatore a questo problema, devo ricreare continuamente ychunk_gen all'interno del ciclo esterno. Dal y è un array di grandi dimensioni, questo sta uccidendo il mio runtime (per elementi ~ 1e6, la creazione di questo generatore richiede ~ 20ms sul mio laptop).
C'è un modo per essere più intelligente su come sto costruendo i miei generatori che aggirano questo problema? O sarà necessario abbandonare del tutto la soluzione del generatore?
(Nota: in pratica, sto usando cython per eseguire questo ciclo stretto, ma tutto quanto sopra si applica a prescindere).
se 'x' e' y' sono elenchi in RAM, quindi l'uso di generatori come quelli che fai non fornisce alcun vantaggio ... inoltre potresti semplicemente eseguire 'counter = len (x) * len (y)' –
Hai provato le list comprehensions invece delle espressioni del generatore e la creazione di entrambi gli elenchi di blocchi prima del ciclo esterno? –
Inoltre, puoi dirci cosa stai effettivamente facendo all'interno del tuo ciclo reale e qual è il tuo compito effettivo? Forse possiamo fornire un aiuto migliore se vediamo il quadro generale. –