Questo è il seguito di Quanto è lento Python? (O quanto è veloce la tua lingua?) .
Si scopre che era un po 'troppo facile ottenere uno speedup x100 per la mia ultima domanda. Per coloro che hanno apprezzato la sfida ma vogliono qualcosa di più difficile in cui possono davvero usare le loro abilità di basso livello, ecco la parte II. La sfida è ottenere un speedup x100 per il seguente codice Python testato sul mio computer.
Per renderlo più difficile, sto usando pypy questa volta. Il tempismo attuale per me è di 1 minuto e 7 secondi usando pypy 2.2.1.
Regole
- La prima persona a inviare il codice che posso eseguire, è corretta ed è x100 volte più veloce sulla mia macchina riceverà un premio di 50 punti.
- Assegnerò la vittoria al codice più veloce dopo una settimana.
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
L'output dovrebbe essere simile a
[6335185, 2526840, 1041967, 439735, 193391, 87083, 40635, 19694]
Devi usare un seme casuale nel tuo codice e sarà accettato qualsiasi generatore di numeri casuali che sia abbastanza buono da dare risposte vicine a quanto sopra.
La mia macchina I tempi verranno eseguiti sulla mia macchina. Questa è un'installazione ubuntu standard su un processore a otto core AMD FX-8350. Questo significa anche che devo essere in grado di eseguire il tuo codice.
Spiegazione del codice
Questo codice scorre su tutte le matrici S di lunghezza n + m-1 create per -1 secondi e 1 secondo. Per ogni array S campiona 1000 array casuali diversi da zero F di lunghezza n costituiti da -1,0 o 1 con probabilità di 1/4, 1/2, / 14 di prendere ciascun valore. Quindi calcola i prodotti interni tra F e ciascuna finestra di S di lunghezza n fino a trovare un prodotto interno diverso da zero. Aggiunge 1 per leadingzerocounts
ogni posizione in cui ha trovato un prodotto interno pari a zero.
Stato
Perl . 2,7 volte rallentamento di @tobyink. (Rispetto a pypy non a cpython.)
J . Accelerazione di 39 volte di @Eelvex.
- C . 59 volte più veloce di @ace.
- Julia . 197 volte più veloce senza includere il tempo di avvio di @ un altro minuto. 8,5 volte più veloce incluso il tempo di avvio (è più veloce usando 4 processori in questo caso di 8).
- Fortran . 438 volte accelerato da @ semi-estrinsic.
- Rpython . 258 volte più veloce di @primo.
- C ++ . 508 volte accelerato da @ilmale.
(Ho smesso di programmare i nuovi miglioramenti perché sono troppo veloci e iter era troppo piccolo.)
È stato sottolineato che i tempi inferiori a un secondo sono inaffidabili e anche alcune lingue hanno un costo di avvio. L'argomento è che se si desidera includere anche il tempo di compilazione di C / C ++ ecc. Ecco i tempi per il codice più veloce con il numero di iterazioni aumentato a 100.000.
- Julia . 42 secondi di @ un altro minuto.
- C ++ . 14 secondi di @GuySirton.
- Fortran . 14s di @ semi-estrinsic.
- C ++ . 12s di @ilmale.
- Rpython . 18s di @primo.
- C ++ . 5s di @Stefan.
Il vincitore è .. Stefan!
Sfida di follow-up pubblicata. Quanto in alto puoi andare? (Una sfida di codifica + algoritmi) . Questo è più difficile.