Özel bir yineleyici ile küçük bir kapsayıcı üzerinde yinelenen oldukça şaşırtıcı performans farklılıkları gibi görünüyor karşılaşıyorum. Birinin bu farklılıkların nereden geldiğini anlamama yardımcı olabileceğini umuyordum.özel yineleyici performansı
İlk önce bazı içerik; Ben getitem uygulayan bir 3d float vektör türüne bir bağlayıcı içeren boost :: python kullanarak bir dizi python uzantısı modülleri yazıyorum. Bunun üzerinden geçmesi mümkün olsa da, oldukça yavaş görünüyor, ancak neden bu kadar açık değil, bu yüzden işlerin nasıl yürüdüğüne dair daha iyi bir fikir edinmek için pythondaki bazı basit özel yineleyicilerle oynamaya karar verdim. Bu yineleyiciler nereden geldiğini olduğunu ...
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]
Sonraki Ben
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()
Bu baskılar (yukarıdaki kod bir modül olarak adlandırılan testiter olduğunu varsayar) sürümüyle gelen timeit modülü ile bir komut dosyası aracılığıyla bunlar ran aşağıdaki
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
üzerinden Beklenildiği piton listiterator oldukça farkla, en hızlı. Bunun python içerisinde bazı sihir optimizasyonlarına bağlı olduğunu farz ediyorum. Jeneratör de MyIterator sınıflarından çok daha hızlıdır, ki bu da yine de pek şaşırmam, ve c'deki tüm işlere bağlı olduğunu varsayalım, ancak bu sadece bir tahmindir. Şimdi diğerleri daha kafa karıştırıcı/şaşırtıcı. Deneme/istisna ifadeleri bu bağlamda göründüğü kadar pahalı mı yoksa başka bir şey mi oluyor?
Bu farklılıkların açıklanmasında yardımcı olacak her şeyden mutluluk duyacağız! Uzun mesaj için özür dilerim.
Sen yerine tuple kullanmayı deneyebilirsiniz [ 'x', 'y', 'z'] (mümkünse): tuple inşaat alittle biraz daha hızlı liste en fazla. –