Wąskim gardłem jest tutaj twoja pętla for
. Pętle Python for
są stosunkowo powolne, więc jeśli potrzebujesz powtórzyć ponad milion pozycji, możesz zyskać dużą szybkość, unikając ich w ogóle. W tym przypadku jest to dość łatwe. Zamiast tego:
for item in range(n):
if ((s1[item])**2 + (s2[item])**2) < 1:
ii = ii + 1
to zrobić:
ii = ((s1 ** 2 + s2 ** 2) < 1).sum()
To działa, ponieważ numpy
posiada wbudowane wsparcie dla optymalizacji operacji tablicowych. Pętla występuje w języku c
zamiast pythona, więc jest znacznie szybsza. Zrobiłem szybki test, dzięki czemu można zobaczyć różnicę:
>>> def estimate_pi_loop(x, y):
... total = 0
... for i in xrange(len(x)):
... if x[i] ** 2 + y[i] ** 2 < 1:
... total += 1
... return total * 4.0/len(x)
...
>>> def estimate_pi_numpy(x, y):
... return ((x ** 2 + y ** 2) < 1).sum()
...
>>> %timeit estimate_pi_loop(x, y)
1 loops, best of 3: 3.33 s per loop
>>> %timeit estimate_pi_numpy(x, y)
100 loops, best of 3: 10.4 ms per loop
Oto kilka przykładów rodzajów działalności, które są możliwe, tak więc masz poczucie jak to działa.
Kwadratura tablicy:
>>> a = numpy.arange(5)
>>> a ** 2
array([ 0, 1, 4, 9, 16])
Dodawanie tablic:
>>> a + a
array([0, 2, 4, 6, 8])
Porównanie tablic:
>>> a > 2
array([False, False, False, True, True], dtype=bool)
Sumowanie wartości logiczne:
>>> (a > 2).sum()
2
Jak zapewne zdajesz sobie sprawę, istnieją szybsze sposoby oszacowania Pi, ale przyznaję, że zawsze podziwiałem prostotę i skuteczność tej metody.
Jakiś powód, dla którego musiałbyś to obliczyć? Dokonano tego już tysiąc razy (np. Przeczytaj z pliku lub zakoduj go). – Caramiriel
Powolność jest nieodłącznym elementem algorytmu - za każdym razem, gdy potrzebna jest jeszcze jedna cyfra precyzji, czas działania wzrasta o 10x. Sprawdź [Pi - nowoczesne poszukiwanie więcej cyfr] (https://en.wikipedia.org/wiki/Pi#Modern_quest_for_more_digits) w celu szybszego podejścia. – Kevin
Czy jest jakikolwiek powód do zbudowania dwóch tablic z góry? Dlaczego nie dostać dwóch liczb 'random.random()' wewnątrz * pętli? Jednak, jak zaznacza @Kevin, ten algorytm jest w zasadzie "O (n)", więc dla dużych 'n' jakiekolwiek zmiany w precyzyjnej implementacji będą jedynie minimalnymi różnicami w stosunku do ogólnego środowiska wykonawczego. – jonrsharpe