Tôi đã cố gắng tối ưu hóa một chương trình tôi đang làm việc với, khi tôi nhận thấy rằng làm value = i % 65536
dường như chạy chậm hơn sau đó thực hiện value = i % (2**16)
.Tại sao lấy mod của một số trong python nhanh hơn với số mũ?
Để kiểm tra điều này, tôi chạy chương trình sau đây:
import cProfile
import pstats
AMOUNT = 100000000
def test1():
for i in xrange(AMOUNT):
value = i % 65536
return
def test2():
for i in xrange(AMOUNT):
value = i % (256**2)
return
def test3():
for i in xrange(AMOUNT):
value = i % (16**4)
return
def test4():
for i in xrange(AMOUNT):
value = i % (4**8)
return
def test5():
for i in xrange(AMOUNT):
value = i % (2**16)
return
def run_tests():
test1()
test2()
test3()
test4()
test5()
return
if __name__ == '__main__':
cProfile.run('run_tests()', 'results')
stats = pstats.Stats('results')
stats.sort_stats('calls', 'nfl')
stats.print_stats()
... mà sản xuất đầu ra sau đây:
Fri May 11 15:11:59 2012 results
8 function calls in 40.473 seconds
Ordered by: call count, name/file/line
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 40.473 40.473 <string>:1(<module>)
1 0.000 0.000 40.473 40.473 test.py:31(run_tests)
1 10.466 10.466 10.466 10.466 test.py:6(test1)
1 7.475 7.475 7.475 7.475 test.py:11(test2)
1 7.485 7.485 7.485 7.485 test.py:16(test3)
1 7.539 7.539 7.539 7.539 test.py:21(test4)
1 7.508 7.508 7.508 7.508 test.py:26(test5)
Sử dụng 65536
là chậm nhất tại 10,466 giây, trong khi làm 256**2
là nhanh nhất tại 7.475 giây (với các giá trị số mũ khác có thể rơi vào giữa). Cấp, sự khác biệt về tốc độ này chỉ đáng chú ý với số lượng lặp lại cao, nhưng tôi vẫn tò mò là tại sao điều này xảy ra.
Tại sao lấy mod của một số bằng 65536
chậm hơn sau đó lấy mod bằng số mũ? Họ nên đánh giá cùng một số, và tôi đã nghĩ rằng sẽ mất nhiều thời gian hơn cho trình thông dịch python để đánh giá đầy đủ các số mũ trước khi dùng mod.
Bằng cách gia hạn, nói chung là hiệu quả hơn để sử dụng quyền hạn của hai trong biểu thức python chứ không phải sau đó gõ đầy đủ số ra? Và mô hình này có đúng với các hoạt động ngoài mô đun hoặc cho các số khác ngoài 2
không?
(btw, tôi đang sử dụng Python 2.7.2 (32 bit) và tôi đã chạy ở trên trên máy tính xách tay 64 bit Windows 7).
EDIT:
Vì vậy, tôi đã cố gắng đảo ngược thứ tự của các chức năng tôi gọi, và bây giờ ngược lại là đúng. Có vẻ như chức năng đầu tiên là ở run_tests
sẽ luôn chạy chậm hơn một chút khi sử dụng cProfile, là lạ. Vì vậy, bài học kinh nghiệm, tôi đoán - profilers là lạ: D
Điều này khá thú vị, nhưng lưu ý rằng sự khác biệt về kết quả cho các thử nghiệm 2 - 5 không thực sự đáng kể. Điều gì sẽ xảy ra nếu bạn chạy thử nghiệm theo thứ tự ngược lại? – Oliver
Bạn chỉ đang gọi chức năng một lần, vì vậy tôi sẽ lo lắng về một số loại chi phí hồ sơ hoặc một cái gì đó ở đó. Tôi không thấy hiệu ứng này bằng cách sử dụng '% timeit' của IPython .... – Dougal
Không thể tái tạo hiệu ứng đó với Python 2.7.3 trên Linux x86-64. –