Tôi đang gặp phải những gì có vẻ như sự khác biệt đáng kể về hiệu năng khi lặp qua một vùng chứa nhỏ với một trình vòng lặp tùy chỉnh. Tôi đã hy vọng một ai đó có thể giúp tôi hiểu được sự khác biệt này đến từ đâu.hiệu suất lặp tùy chỉnh
Đầu tiên một số ngữ cảnh; Tôi đang viết một số mô-đun mở rộng python bằng cách sử dụng boost :: python, một trong số đó có chứa một ràng buộc với một loại vector nổi 3d thực hiện getitem. Vì nó có khả năng lặp lại nó, tuy nhiên nó có vẻ khá chậm, nhưng nó không rõ ràng vì sao tôi quyết định chơi xung quanh với một số trình vòng lặp tùy chỉnh đơn giản trong python để có ý tưởng tốt hơn về cách mọi thứ hoạt động. Đó là nơi những vòng lặp đến từ ...
class MyIterator1(object):
__slots__ = ['values', 'popfn']
def __init__(self):
self.values = ['x', 'y', 'z']
self.popfn = self.values.pop
def __length_hint__(self):
return 3
def __iter__(self):
return self
def next(self):
try:
return self.popfn()
except IndexError:
raise StopIteration
class MyIterator2(object):
__slots__ = ['values', 'itfn']
def __init__(self):
self.values = ['x', 'y', 'z']
it = iter(self.values)
self.itfn = it.next
def __length_hint__(self):
return 3
def __iter__(self):
return self
def next(self):
return self.itfn()
class MyIterator3(object):
__slots__ = ['values', 'i']
def __init__(self):
self.values = ['x', 'y', 'z']
self.i = 0
def __length_hint__(self):
return 3
def __iter__(self):
return self
def next(self):
if self.i >= 3:
raise StopIteration
value = self.values[self.i]
self.i += 1
return value
def MyIterator4():
val = ['x', 'y', 'z']
yield val[0]
yield val[1]
yield val[2]
Tiếp theo, tôi chạy này thông qua một kịch bản với các module timeit (mà giả mã trên là trong một module gọi là testiter)
import timeit
timer1 = timeit.Timer('r = list(testiter.MyIterator1())', 'import testiter')
timer2 = timeit.Timer('r = list(testiter.MyIterator2())', 'import testiter')
timer3 = timeit.Timer('r = list(testiter.MyIterator3())', 'import testiter')
timer4 = timeit.Timer('r = list(testiter.MyIterator4())', 'import testiter')
timer5 = timeit.Timer('r = list(iter(["x", "y", "z"]))', 'import testiter')
print 'list(testiter.MyIterator1())'
print timer1.timeit()
print "\n"
print 'list(testiter.MyIterator2())'
print timer2.timeit()
print "\n"
print 'list(testiter.MyIterator3())'
print timer3.timeit()
print "\n"
print 'list(testiter.MyIterator4())'
print timer4.timeit()
print "\n"
print 'list(iter(["x", "y", "z"]))'
print timer5.timeit()
in này ra sau đây
list(testiter.MyIterator1())
8.5735929
list(testiter.MyIterator2())
5.28959393501
list(testiter.MyIterator3())
6.11230111122
list(testiter.MyIterator4())
2.31263613701
list(iter(["x", "y", "z"]))
1.26243281364
Không có gì đáng ngạc nhiên khi trình xếp hạng python là nhanh nhất, bằng một lề. Tôi cho rằng đây là một số tối ưu hóa ma thuật trong python. Máy phát cũng nhanh hơn đáng kể so với các lớp MyIterator, một lần nữa tôi không ngạc nhiên lắm, và giả định là do tất cả các công việc đang được thực hiện trong c, tuy nhiên đó chỉ là một phỏng đoán. Bây giờ những người khác là khó hiểu/supprising. Có phải thử/ngoại trừ các câu lệnh đắt tiền như chúng có vẻ trong ngữ cảnh này hay là cái gì khác đang diễn ra?
Bất kỳ trợ giúp nào trong việc giải thích những khác biệt này sẽ được đánh giá cao! Xin lỗi vì bài viết dài.
Bạn có thể thử dùng tuple thay vì ['x', 'y', 'z'] (nếu có thể): xây dựng tuple nhanh hơn một chút so với danh sách. –