¿Por qué islice(permutations) es 100 veces más rápido si mantengo una referencia al iterador subyacente?
Iterar a través de islice(permutations(a), n)
es de alguna manera 100 veces más rápido si mantengo una referencia extra al iterador permutations
. Alternando entre con y sin la referencia extra:
2.1 ms con
202.2 ms sin
2.1 ms con
195.8 ms sin
2.1 ms con
192.4 ms sin
¿Qué está pasando?
Código completo (¡Pruébalo en línea!):
from timeit import timeit
from itertools import permutations, islice
from collections import deque
a = range(10 * 7)
n = 10 * 5
for label in ['con', 'sin'] * 3:
if label == 'con':
perms = islice((foo := permutations(a)), n)
else:
perms = islice(permutations(a), n)
next(perms)
t = timeit(lambda: deque(perms, 0), number=1)
print('%5.1f ms ' % (t * 1e3), label)
davy.ai
La razón de la diferencia significativa en el rendimiento se debe al hecho de que el iterador
permutations
genera todas las posibles permutaciones de antemano y las devuelve una a una al ser iteradas. Cuandoperms
se define dentro de cada iteración del bucle sin una referencia adicional,permutations(a)
debe ser llamado repetidamente, regenerando todas las posibles permutaciones cada vez, lo cual consume mucho tiempo. Sin embargo, cuando se mantiene una referencia adicional en el buclewith
asignandopermutations(a)
a la variablefoo
, el generador se crea solo una vez y puede ser reutilizado en cada iteración del bucle con la funciónislice
. Esto reduce considerablemente el tiempo empleado en generar permutaciones, lo que resulta en una iteración mucho más rápida a través deislice(permutations(a), n)
. Por lo tanto, se recomienda mantener una referencia adicional apermutations
para mejorar el rendimiento al iterar a través de permutaciones grandes.