Ceci est un suivi de la lenteur de Python. (Ou à quelle vitesse votre langue est-elle?) .
Il s’est avéré qu’il était un peu trop facile d’obtenir une accélération x100 pour ma dernière question. Pour la partie qui a aimé le défi mais qui veut quelque chose de plus difficile où ils peuvent vraiment utiliser leurs compétences de bas niveau, voici la partie II. Le défi consiste à obtenir une accélération x100 pour le code python suivant, testé sur mon ordinateur.
Pour rendre les choses plus difficiles, j'utilise pypy cette fois-ci. Pour moi, le timing actuel est de 1 minute et 7 secondes avec Pypy 2.2.1.
Règles
- La première personne à soumettre du code que je peux exécuter est correcte et x100 fois plus rapide sur ma machine se verra attribuer une prime de 50 points.
- Je vais attribuer la victoire au code le plus rapide après une semaine.
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 sortie doit être similaire à
[6335185, 2526840, 1041967, 439735, 193391, 87083, 40635, 19694]
Vous devez utiliser une graine aléatoire dans votre code et tout générateur de nombre aléatoire suffisant pour donner des réponses proches de ce qui précède sera accepté.
Ma machine Les timings seront exécutés sur ma machine. Il s’agit d’une installation ubuntu standard sur un processeur à huit cœurs AMD FX-8350. Cela signifie également que je dois pouvoir exécuter votre code.
Explication du code
Ce code itère sur tous les tableaux S de longueur n + m-1 constitués de -1 et de 1. Pour chaque tableau S, il échantillonne 1000 tableaux aléatoires non nuls F de longueur n constituée de -1,0 ou 1 avec une probabilité de 1/4, 1/2, / 14 de la prise de chaque valeur. Il calcule ensuite les produits internes entre F et chaque fenêtre de S de longueur n jusqu'à trouver un produit interne non nul. Il ajoute 1 leadingzerocounts
à chaque position où il a trouvé un produit intérieur nul.
Statut
Perl . Ralentissement de 2,7 fois par @tobyink. (Comparé à pypy pas cpython.)
J . 39 fois plus rapide par @Eelvex.
- C . 59 fois plus rapide par @ace.
- Julia . 197 fois plus rapide sans compter le temps de démarrage de @ une minute de plus. 8,5 fois plus rapide, temps de démarrage compris (l'utilisation de 4 processeurs est plus rapide que 8).
- Fortran . 438 fois plus rapide en @ semi-extrinsèque.
- Rpython . 258 fois plus rapide par @primo.
- C ++ . 508 fois plus rapide par @ilmale.
(J'ai arrêté de chronométrer les nouvelles améliorations car elles sont trop rapides et trop petites.)
Il a été souligné que les durées inférieures à une seconde ne sont pas fiables et que certaines langues ont un coût de démarrage. L'argument est que si vous voulez inclure cela, vous devez également inclure le temps de compilation de C / C ++, etc. Voici les timings pour le code le plus rapide avec le nombre d'itérations porté à 100 000.
- Julia . 42 secondes par @ une minute de plus.
- C ++ . 14 secondes par @GuySirton.
- Fortran . 14s par @ semi-extrinsiques.
- C ++ . 12s par @ilmale.
- Rpython . 18s par @primo.
- C ++ . 5s de @Stefan.
Le gagnant est .. Stefan!
Défi de suivi affiché. À quelle hauteur pouvez-vous aller? (Un défi de codage + algorithmes) . Celui-ci est plus difficile.