2017-06-01 62 views
7

Ben func fonksiyonun performansını artırmak için çalışıyordum ve aX listenin nasıl basit bir değişiklik Performansın biraz iyileştirdiğini bulundu:Neden rastgele bir listeyi sipariş edilen bir listeyi işlemeden çok daha hızlı işliyor?

import timeit 
import numpy as np 

def func(a, b): 
    return [_ for _ in a if _ not in b] 

Na, Nb = 10000, 5000 
b = list(np.random.randint(1000, size=Nb)) 

# Ordered list of Na integers 
a1 = [_ for _ in range(Na)] 
# Random list of Na integers 
a2 = list(np.random.randint(Na, size=Na)) 
# Ordered list of Na integers generated with numpy 
a3 = list(np.arange(Na)) 

start_time = timeit.default_timer() 
ab1 = func(a1, b) 
abt1 = timeit.default_timer() - start_time 
print("Time ab1", abt1) 

start_time = timeit.default_timer() 
ab2 = func(a2, b) 
abt2 = timeit.default_timer() - start_time 
print("Time ab2", abt2) 

start_time = timeit.default_timer() 
ab3 = func(a3, b) 
abt3 = timeit.default_timer() - start_time 
print("Time ab3", abt3) 

print("Ratio 1/2:", abt1/abt2) 
print("Ratio 1/3:", abt1/abt3) 

Python 2.7.13 bu sonuçlanır: Python

('Time ab1', 5.296088933944702) 
('Time ab2', 1.5520200729370117) 
('Time ab3', 1.5581469535827637) 
('Ratio 1/2:', 3.412384302428827) 
('Ratio 1/3:', 3.3989662667998095) 

farkı 3.5.2

bile büyüktür:

Time ab1 6.758207322000089 
Time ab2 1.5693355060011527 
Time ab3 1.5148192759988888 
Ratio 1/2: 4.306413317073784 
Ratio 1/3: 4.461395117608107 
Sorum şu yüzden: ( a1 veya a3 yani):Bir sıralı liste tamsayılar işlenmesi gerektiği

Neden rastgele liste numpy ile oluşturulan sıralı liste değil çok daha hızlı işlenir?

+0

Bu aptalca bir soru olabilir, ancak * işleyemezsiniz * veya * siparişi * listeyi ** yeniden sipariş veremez misiniz? –

+2

Bu adil bir test midir? "A1" listesindeki maksimum değer 10000 (listenin uzunluğu) olacaktır; burada "a2" listesindeki maksimum değer, 0 ile 1000 arasında rastgele bir sayı olacağı için 1000 olacaktır. _ _ aralığında (Na) için] 'ile' a1 = [_ // 10 aralığında (Na) için] '4.6 oranının neden daha hızlı olduğundan hala emin değildir. Ya da belki de bunu yanlış anladım. –

+0

@ Alessi42 geçerli bir noktadır. Bu farkı düzeltmek için soruyu düzenleyeceğim. Teşekkür ederim! – Gabriel

cevap

7

Sizin b, a2 ve a3 listeleri, NumPy skalerler listeleridir. NumPy skalerlerinin sıradan Python skalerlerine benzetilmesi, lot ekstra tip kontrol ve zorlama gerektirir, bu nedenle NumPy skalerlerini sıradan Python skalerleriyle karşılaştırmak zorunda olan func(a1, b) testi, en yavaşı gösterir.

b, bir Python ints listesi yaparsanız (list işlevi yerine tolist method'u çağırarak), zaman farkı tersine çevrilir.

Görevinizi gerçekleştirmek için Python set s veya NumPy'nin set-like operations modellerini kullanmayı düşünebilirsiniz.

1

here hakkında tartışıldığı üzere, numpy dizileri python listelerinden çok daha hızlıdır. Bu nedenle, list() işlevini çağırdığınızda, numpy dizileri hala bir numpy dizisi kullandığınızdan daha hızlı görünür.

düzenli Python için bir NumPy dizisi aşağı tüm yol nesneleri (user2357112 belirttiği gibi) ve performans farklılıkları ortadan bkz dönüştürür numpy .tolist() fonksiyonunu kullanarak:

import timeit 
import numpy as np 

def func(a, b): 
    return [_ for _ in a if _ not in b] 

Na, Nb = 10000, 5000 
b = list(np.random.randint(Na, size=Nb)) # len: 5000, max: 9999 

# Ordered list of Na integers 
a1 = [_ for _ in range(Na)] # len: 10000, max: 9999 
# Random list of Na integers 
a2 = np.random.randint(Na, size=Na).tolist() # len: 10000, max: 9999 
# Ordered list of Na integers generated with numpy 
a3 = np.arange(Na).tolist() 

start_time = timeit.default_timer() 
ab1 = func(a1, b) 
abt1 = timeit.default_timer() - start_time 
print("Time ab1", abt1) 

start_time = timeit.default_timer() 
ab2 = func(a2, b) 
abt2 = timeit.default_timer() - start_time 
print("Time ab2", abt2) 

start_time = timeit.default_timer() 
ab3 = func(a3, b) 
abt3 = timeit.default_timer() - start_time 
print("Time ab3", abt3) 

print("Ratio 1/2:", abt1/abt2) 
print("Ratio 1/3:", abt1/abt3) 

#Time ab1 4.622085004015502 
#Time ab2 4.598610720638726 
#Time ab3 4.63976530848255 
#Ratio 1/2: 1.005104646773301 
#Ratio 1/3: 0.9961893968139456 

Umarım bu ilk soru cevaplar! senin a1 liste sıradan Python ints listesidir süre

+3

için bir kaynak verebilir misiniz? Bu yüzden, list() işlevini çağırdığınızda numpy dizisi hala numpy dizisi kullandığınız gibi daha hızlı görünüyor? –

+0

Artık ndarray için dokümanlar ekledim.tolist() 'ancak bir liste bulamıyor gibiyim, çünkü liste()' aynı şeyi yapmıyorsa, bunun için bir işlev eklediyse, varsayılan olarak –

+0

'list ' bir liste oluşturur. 'list 'bir numPy dizisini sıradan Python nesnelerine dönüştürür, çok boyutlu diziler için bir yuvalanmış liste oluşturur ve tüm skalerleri sıradan Python skalerlerine dönüştürür. – user2357112