To kontynuacja tego, jak bardzo wolno jest Python? (Lub jak szybki jest twój język?) .
Okazuje się, że dla mojego ostatniego pytania trochę za łatwo było uzyskać przyspieszenie x100. Dla tych, którzy lubili wyzwania, ale chcą czegoś trudniejszego, w którym mogliby naprawdę wykorzystać swoje umiejętności niskiego poziomu, oto część II. Wyzwanie polega na uzyskaniu przyspieszenia x100 dla następującego kodu python przetestowanego na moim komputerze.
Aby utrudnić, tym razem używam pypy. Obecny czas dla mnie to 1 minuta i 7 sekund przy użyciu pypy 2.2.1.
Zasady
- Pierwsza osoba, która prześle kod, który mogę uruchomić, jest poprawna i jest 100 razy szybsza na moim komputerze, otrzyma nagrodę w wysokości 50 punktów.
- Zwycięstwo przyznam najszybszemu kodowi po tygodniu.
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
Dane wyjściowe powinny być podobne do
[6335185, 2526840, 1041967, 439735, 193391, 87083, 40635, 19694]
Musisz użyć losowego ziarna w kodzie, a dowolny generator liczb losowych, który jest wystarczająco dobry, aby dać odpowiedzi zbliżone do powyższego, zostanie zaakceptowany.
Moja maszyna Czasy zostaną uruchomione na moim komputerze. Jest to standardowa instalacja ubuntu na ośmiordzeniowym procesorze AMD FX-8350. Oznacza to również, że muszę być w stanie uruchomić Twój kod.
Objaśnienie kodu
Ten kod iteruje wszystkie tablice S o długości n + m-1, które składają się na -1s i 1s. Dla każdej tablicy S próbkuje 1000 niezerowych losowych tablic F o długości n składającej się z -1,0 lub 1 z prawdopodobieństwem 1/4, 1/2, / 14 pobrania każdej wartości. Następnie oblicza iloczyn wewnętrzny między F i każdym oknem S o długości n, aż znajdzie niezerowy iloczyn wewnętrzny. Dodaje 1 do leadingzerocounts
każdej pozycji, w której znalazł zero wewnętrznego produktu.
Status
Perl . 2,7 razy spowolnienie przez @tobyink. (W porównaniu do pypy nie cpython.)
J . 39-krotne przyspieszenie o @Eelvex.
- C . 59 razy przyspieszyć @ace.
- Julia . 197 razy szybszy, nie wliczając czasu rozruchu o jeszcze jedną minutę. 8,5 razy szybsze, w tym czas rozruchu (w tym przypadku jest szybszy przy użyciu 4 procesorów niż 8).
- Fortran . 438 razy przyspieszenie o @ semi-extrinsic.
- Rpython . 258 razy przyspieszyć @primo.
- C ++ . 508 razy przyspieszenie @ilmale.
(Przestałem mierzyć czas nowych ulepszeń, ponieważ są one zbyt szybkie, a iteracja była za mała).
Zwrócono uwagę, że czasy poniżej jednej sekundy są niewiarygodne, a także niektóre języki mają koszty początkowe. Argument jest taki, że jeśli chcesz dołączyć, powinieneś również uwzględnić czas kompilacji C / C ++ itp. Oto czasy najszybszego kodu z liczbą iteracji zwiększoną do 100 000.
- Julia . 42 sekundy do @ jeszcze minuty.
- C ++ . 14 sekund autorstwa @GuySirton.
- Fortran . 14s @ semi-extrinsic.
- C ++ . 12s przez @ilmale.
- Rpython . 18s @primo.
- C ++ . 5s @Stefan.
Zwycięzcą jest ... Stefan!
Opublikowane wyzwanie uzupełniające. Jak wysoko możesz iść? (Wyzwanie kodowania + algorytmy) . Ten jest trudniejszy.