Nút cổ chai ở đây thực sự là vòng lặp for
của bạn. Python for
vòng là tương đối chậm, vì vậy nếu bạn cần phải lặp lại hơn một triệu mục, bạn có thể đạt được rất nhiều tốc độ bằng cách tránh chúng hoàn toàn. Trong trường hợp này, nó khá dễ dàng. Thay vì điều này:
for item in range(n):
if ((s1[item])**2 + (s2[item])**2) < 1:
ii = ii + 1
làm điều này:
ii = ((s1 ** 2 + s2 ** 2) < 1).sum()
này hoạt động vì numpy
đã xây dựng-in hỗ trợ cho các hoạt động mảng tối ưu. Việc lặp xảy ra trong c
thay vì python, vì vậy nó nhanh hơn nhiều. Tôi đã thực hiện một bài kiểm tra nhanh để bạn có thể thấy sự khác biệt:
>>> 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
Dưới đây là một vài ví dụ về các loại hoạt động có thể, để bạn hiểu cách hoạt động của nó.
Squaring một mảng:
>>> a = numpy.arange(5)
>>> a ** 2
array([ 0, 1, 4, 9, 16])
mảng Thêm:
>>> a + a
array([0, 2, 4, 6, 8])
mảng So sánh:
>>> a > 2
array([False, False, False, True, True], dtype=bool)
Tổng giá trị boolean:
>>> (a > 2).sum()
2
Như bạn có thể nhận ra, có những cách nhanh hơn để ước tính Pi, nhưng tôi sẽ thừa nhận rằng tôi luôn ngưỡng mộ sự đơn giản và hiệu quả của phương pháp này.
Bất kỳ lý do nào bạn cần tính toán điều này? Điều này đã được thực hiện hàng ngàn lần (ví dụ, đọc nó từ tập tin, hoặc mã hóa nó). – Caramiriel
Sự chậm chạp chỉ là cố hữu trong thuật toán - mỗi khi bạn muốn thêm một chữ số chính xác, thời gian chạy tăng gấp 10 lần. Xem [Pi - quest hiện đại để biết thêm chữ số] (https://en.wikipedia.org/wiki/Pi#Modern_quest_for_more_digits) để có cách tiếp cận nhanh hơn. – Kevin
Có lý do nào để xây dựng hai mảng lên phía trước không? Tại sao không nhận được hai 'random.random()' số * bên trong * vòng lặp? Tuy nhiên, như @Kevin chỉ ra, thuật toán này là về mặt cơ bản 'O (n)', vì vậy đối với các 'n' lớn, bất kỳ thay đổi nào đối với việc triển khai chính xác sẽ chỉ tạo ra sự khác biệt tối thiểu cho thời gian chạy tổng thể. – jonrsharpe