Este es un seguimiento de ¿Qué tan lento es realmente Python? (¿O qué tan rápido es tu idioma?) .
Resulta que fue un poco demasiado fácil obtener una aceleración x100 para mi última pregunta. Para aquellos que han disfrutado el desafío pero quieren algo más difícil donde realmente pueden usar sus habilidades de bajo nivel, aquí está la parte II. El desafío es obtener una aceleración x100 para el siguiente código de Python según lo probado en mi computadora.
Para hacerlo más difícil, estoy usando pypy esta vez. El tiempo actual para mí es de 1 minuto y 7 segundos usando pypy 2.2.1.
Reglas
- La primera persona en enviar el código que puedo ejecutar, es correcta y es x100 veces más rápido en mi máquina, recibirá una recompensa de 50 puntos.
- Otorgaré la victoria al código más rápido después de una semana.
import itertools
import operator
import random
n = 8
m = 8
iters = 1000
# creates an array of 0s with length m
# [0, 0, 0, 0, 0, 0, 0, 0]
leadingzerocounts = [0]*m
# itertools.product creates an array of all possible combinations of the
# args passed to it.
#
# Ex:
# itertools.product("ABCD", "xy") --> Ax Ay Bx By Cx Cy Dx Dy
# itertools.product("AB", repeat=5) --> [
# ('A', 'A', 'A', 'A', 'A'),
# ('A', 'A', 'A', 'A', 'B'),
# ('A', 'A', 'A', 'B', 'A'),
# ('A', 'A', 'A', 'B', 'B'),
# etc.
# ]
for S in itertools.product([-1,1], repeat = n+m-1):
for i in xrange(iters):
F = [random.choice([-1,0,0,1]) for j in xrange(n)]
# if the array is made up of only zeros keep recreating it until
# there is at least one nonzero value.
while not any(F):
F = [random.choice([-1,0,0,1]) for j in xrange(n)]
j = 0
while (j < m and sum(map(operator.mul, F, S[j:j+n])) == 0):
leadingzerocounts[j] +=1
j += 1
print leadingzerocounts
La salida debe ser similar a
[6335185, 2526840, 1041967, 439735, 193391, 87083, 40635, 19694]
Debe usar una semilla aleatoria en su código y se aceptará cualquier generador de números aleatorios que sea lo suficientemente bueno como para dar respuestas cercanas a las anteriores.
Mi máquina Los tiempos se ejecutarán en mi máquina. Esta es una instalación estándar de ubuntu en un procesador AMD FX-8350 de ocho núcleos. Esto también significa que necesito poder ejecutar su código.
Explicación de código
Este código itera sobre todas las matrices S de longitud n + m-1 que están formadas por -1s y 1s. Para cada matriz S, muestra 1000 matrices aleatorias distintas de cero F de longitud n formadas por -1,0 o 1 con probabilidad de 1/4, 1/2, / 14 de tomar cada valor. Luego calcula los productos internos entre F y cada ventana de S de longitud n hasta que encuentra un producto interno distinto de cero. Agrega 1 a leadingzerocounts
cada posición donde encontró un producto interno cero.
Estado
Perl . 2.7 veces la ralentización por @tobyink. (En comparación con pypy no cpython).
J . 39 veces más velocidad por @Eelvex.
- C . 59 veces acelerado por @ace.
- Julia . 197 veces más rápido sin incluir el tiempo de inicio en un minuto más. 8.5 veces más rápido, incluido el tiempo de inicio (en este caso, es más rápido usar 4 procesadores que 8).
- Fortran . 438 veces más rápido por @ semi-extrínseco.
- Rpython . 258 veces acelerado por @primo.
- C ++ . 508 veces acelerado por @ilmale.
(Dejé de cronometrar las nuevas mejoras porque son demasiado rápidas e iters era demasiado pequeño).
Se señaló que los tiempos por debajo de un segundo no son confiables y también algunos idiomas tienen un costo inicial. El argumento es que si va a incluir eso, también debe incluir el tiempo de compilación de C / C ++, etc. Aquí están los tiempos para el código más rápido con el número de iteraciones aumentado a 100,000.
- Julia . 42 segundos por @ un minuto más.
- C ++ . 14 segundos por @GuySirton.
- Fortran . 14s por @ semi-extrinsic.
- C ++ . 12s por @ilmale.
- Rpython . 18s por @primo.
- C ++ . 5s por @Stefan.
El ganador es ... ¡Stefan!
Reto de seguimiento publicado. ¿Qué tan alto puedes llegar? (Un desafío de codificación + algoritmos) . Este es más difícil.