簡體   English   中英

Python中“和”理解的速度

[英]Speed of “sum” comprehension in Python

我的印象是使用sum構造要比運行for循環快得多。 但是,在以下代碼中,for循環實際上運行得更快:

import time

Score = [[3,4,5,6,7,8] for i in range(40)]

a=[0,1,2,3,4,5,4,5,2,1,3,0,5,1,0,3,4,2,2,4,4,5,1,2,5,4,3,2,0,1,1,0,2,0,0,0,1,3,2,1]

def ver1():
    for i in range(100000):
        total = 0
        for j in range(40):
            total+=Score[j][a[j]]
    print (total)

def ver2():
    for i in range(100000):
        total = sum(Score[j][a[j]] for j in range(40))
    print (total)


t0 = time.time()
ver1()
t1 = time.time()
ver2()
t2 = time.time()

print("Version 1 time: ", t1-t0)
print("Version 2 time: ", t2-t1)

輸出是:

208
208
Version 1 time:  0.9300529956817627
Version 2 time:  1.066061019897461

難道我做錯了什么? 有沒有辦法更快地做到這一點?

(請注意,這只是我設置的一個演示,在我的實際應用中,分數不會以這種方式重復)

一些額外的信息:這是在64位的Python 3.4.4上運行,在Windows 7 64位上,在i7上運行。

這似乎取決於系統,可能是python版本。 在我的系統上,差異大約是13%:

python sum.py 
208
208
('Version 1 time: ', 0.6371259689331055)
('Version 2 time: ', 0.7342419624328613)

這兩個版本不是測量sum而不是手動循環,因為循環“主體”不相同。 ver2做了更多工作,因為它創建了100000 ver1成器表達式,而ver1的循環體幾乎是微不足道的,但它為每次迭代創建了一個包含40個元素的列表。 您可以將示例更改為相同,然后您可以看到sum的效果:

def ver1():
    r = [Score[j][a[j]] for j in range(40)]
    for i in xrange(100000):
        total = 0
        for j in r:
            total+=j
    print (total)

def ver2():
    r = [Score[j][a[j]] for j in xrange(40)]
    for i in xrange(100000):
        total = sum(r)
    print (total)

我已經將所有內容從內部循環體中移出並且從sum調用中移除,以確保我們僅測量手工制作循環的開銷。 使用xrange而不是range進一步改善整個運行時,但這適用於兩個版本,因此不會更改比較。 我系統上修改代碼的結果是:

python sum.py
208
208
('Version 1 time: ', 0.2034609317779541)
('Version 2 time: ', 0.04234910011291504)

ver2ver1快五倍。 這是使用sum而不是手工制作循環的純粹性能增益。

ShadowRanger關於查找問題的評論的啟發,我修改了示例以比較原始代碼並檢查綁定符號的查找:

def gen(s,b):
    for j in xrange(40):
        yield s[j][b[j]]

def ver2():
    for i in range(100000):
        total = sum(gen(Score, a))
    print (total)

我創建了一個小型自定義生成器,它在本地綁定Scorea以防止在父作用域中進行昂貴的查找。 執行此:

python sum.py
208
208
('Version 1 time: ', 0.6167840957641602)
('Version 2 time: ', 0.6198039054870605)

單獨的符號查找占運行時的約12%。

由於j迭代兩個列表,我想我會看到zip是否更好用了:

def ver3():
    for i in range(100000):
        total = sum(s[i] for s,i in zip(Score,a))
    print (total)

在Py2上,它比版本2慢大約30%,但在Py3上比版本1快約20%。如果我將zip更改為izip (從itertools導入),這izip時間縮短到版本1和版本2之間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM