2016-05-05 21 views
11

Bu question ve benim answer benim Python 2.7 ve Python 3.4 arasındaki bu benzersiz fark hakkında beni düşündüm. Ben sürekli 0.165~ olsun, Python 2.7 olarakPython 3.4'te dilimleme gerçekten daha yavaş mı?

import timeit 
import dis 

c = 1000000 
r = range(c) 
def slow(): 
    for pos in range(c): 
     r[pos:pos+3] 

dis.dis(slow) 

time = timeit.Timer(lambda: slow()).timeit(number=1) 
print('%3.3f' % time) 

ve Python 3.4 için ben sürekli 0.554~ olsun: Basit bir örnek kod alın. Söküler arasındaki tek önemli fark Python 2.7 SLICE+3 bayt kodunu yayarken Python 3.4 BUILD_SLICE ya da BINARY_SUBSCR izler. Diğer sorudan potansiyel yavaşlama için adayları, yani dizeleri ve xrange'un Python 3.4'te bulunmadığı gerçeğini not ettiğimi not etmeliyim (ki bu da zaten range sınıfına benzerdi).

itertools'islice öğesinin kullanılması, ikisi arasındaki neredeyse aynı zamanlamaları verir; dolayısıyla, buradaki farkın nedeni olan dilimlemenin olduğundan şüpheleniyorum.

Bu neden oluyor ve davranıştaki değişikliği belgeleyen yetkili bir kaynağın bağlantısı var mı?

DÜZENLEME: Yanıta yanıt olarak, list adresindeki range nesnelerini dikkatlice hızlandırılmış bir şekilde verdim. Ancak, timeit'daki yineleme sayısını arttırdığımda, zamanlama farklılıklarının daha da büyüdüğünü fark ettim. Bir akıl sağlığı kontrolü olarak, ne olacağını görmek için dilimlemeyi None ile değiştirdim.

timeit numaralı 500 yineleme.

c = 1000000 
r = list(range(c)) 
def slow(): 
    for pos in r: 
     None 

sırasıyla 10.688 ve 9.915 elde edilir. For döngüsünü for pos in islice(r, 0, c, 3) ile değiştirmek, sırasıyla 7.626 ve 6.270 verir. Sırasıyla None'un r[pos] ile değiştirilmesi, 20~ ve 28~'u verdi. r[pos:pos+3], sırasıyla 67.531 ve 106.784 verir.

Gördüğünüz gibi, zamanlama farklılıkları çok büyük. Yine, sorun hala doğrudan range ile ilgili değildir ikna oldum.

+0

Python 2'de 'range' veya' xrange' kullanıyor muydunuz? – cdarke

+0

Yeniden deneyin, r = list (range (c)) 'ile. –

+0

Python 3 'range' ve Python 2' xrange' nesneleri bu bağlamda benzer değildir. Python 3 'range' nesneleri dilimlemeyi destekler, Python 2' xrange' nesneleri dilimlemeyi desteklemez. – cdarke

cevap

10

Python 2.7'de, bir liste üzerinde yineleme yapıyor ve bir listeyi dilimliyorsunuz. Python 3.4'de, rangerange'u dilimlemek üzere range ve üzerinden devam edersiniz. Hem Python sürümlerinde bir liste ile bir test çalıştırdığınızda

:

from __future__ import print_function 
import timeit 
print(timeit.timeit('x[5:8]', setup='x = list(range(10))')) 

Ben 0.243554830551 seconds on Python 2.7 ve 0.29082867689430714 seconds on Python 3.4, çok daha küçük bir fark olsun.


Eğer range nesneyi ortadan kaldırarak sonra göreceği performans farkı çok daha küçüktür. Öncelikle iki faktörden geliyor: Python 3'de biraz daha yavaş oluyor ve Python 3'ün dilimleme için bir dilim nesnesiyle __getitem__'dan geçmesi gerekiyor, Python 2 ise __getslice__.

Gördüğünüz zamanlama farkını r[pos]; Bu testte bazı karıştırıcı faktörler almış olabilirsiniz.

+1

Yineleme sayısının artırılması, zamanlama farklılıklarında daha büyük ve daha büyük boşluklar göstermeye başlar. 10 iterasyon için sırasıyla 1.352' ve '2.171'. Burada ne eksik olduğumdan emin değilim. –

+0

@ user6292850: Bu testi nasıl çalıştırıyorsunuz? – user2357112

+1

Sadece "timeit" içindeki sayı parametresini arttırıyorum ve "python test.py" yi çalıştırıyorum, ardından "python3 test.py". –

İlgili konular