[英]for loop to list comprehension or map in python
我試圖稍微提高一些python代碼的速度,因此嘗試將標准for循環移動到列表理解或map調用:
buf = [0 for i in range(self.numLEDs * 3)]
temp = [0,0,0]
for x in range(self.numLEDs):
r = data[x*3]
g = data[x*3+1]
b = data[x*3+2]
temp[self.c_order[0]] = self.gamma[r]
temp[self.c_order[1]] = self.gamma[g]
temp[self.c_order[2]] = self.gamma[b]
buf[x * 3:x * 3 + 3] = temp
c_order只是另一個列表,在這種情況下為[1,2,0]。 它控制某些RGB像素的通道順序。 gamma是一個256個元素長的列表,其中包含8位通道值中每個值的經過gamma校正的值。
我想做的就是以某種方式從這部分代碼中完全刪除對循環標准的使用。 我已經設法在沒有通道交換的情況下做到了這一點,但是有了伽瑪校正,它的速度快了一倍。 像這樣:
corrected = [gamma[i] for i in data]
buf[0:len(corrected)] = corrected
我如何在沒有for循環的情況下交換列表元素的順序?
您可以在幾行中以numpy
完成所有工作,並且速度稍快一些:
In [69]:
gamma=list(np.random.rand(256))
numLEDs=10
data=list(np.random.randint(0,256,30))
c_order=[0,1,2]
In [70]:
%%timeit
buf = [0 for i in range(numLEDs * 3)]
temp = [0,0,0]
for x in range(numLEDs):
r = data[x*3]
g = data[x*3+1]
b = data[x*3+2]
temp[c_order[0]] = gamma[r]
temp[c_order[1]] = gamma[g]
temp[c_order[2]] = gamma[b]
buf[x * 3:x * 3 + 3] = temp
10000 loops, best of 3: 47.3 µs per loop
In [85]:
gamma=np.array(gamma)
data=np.array(data)
In [86]:
%%timeit
data_array=data.reshape(3, -1, order='F')
np.take(gamma[data_array], c_order, axis=0).ravel(order='F')
10000 loops, best of 3: 38.3 µs per loop
當您有很多LED時, numpy
版本將比loop
版本快得多:
In [98]:
gamma=list(np.random.rand(256))
numLEDs=1000
data=list(np.random.randint(0,256,3000))
c_order=[0,1,2]
In [99]:
%%timeit
buf = [0 for i in range(numLEDs * 3)]
temp = [0,0,0]
for x in range(numLEDs):
r = data[x*3]
g = data[x*3+1]
b = data[x*3+2]
temp[c_order[0]] = gamma[r]
temp[c_order[1]] = gamma[g]
temp[c_order[2]] = gamma[b]
buf[x * 3:x * 3 + 3] = temp
100 loops, best of 3: 4.08 ms per loop
In [100]:
gamma=np.array(gamma)
data=np.array(data)
In [101]:
%%timeit
data_array=data.reshape(3, -1, order='F')
np.take(gamma[data_array], c_order, axis=0).ravel(order='F')
1000 loops, best of 3: 244 µs per loop
因此,您需要沒有任何擴展庫的純python代碼。
要加速代碼:
這是代碼:
class Test(object):
def __init__(self, n):
self.numLEDs = n
self.c_order = [1, 2, 0]
self.gamma = [i // 2 for i in range(256)]
def do1(self, data):
buf = [0 for i in range(self.numLEDs * 3)]
temp = [0,0,0]
for x in range(self.numLEDs):
r = data[x*3]
g = data[x*3+1]
b = data[x*3+2]
temp[self.c_order[0]] = self.gamma[r]
temp[self.c_order[1]] = self.gamma[g]
temp[self.c_order[2]] = self.gamma[b]
buf[x * 3:x * 3 + 3] = temp
return buf
def do2(self, data):
buf = [0] * (self.numLEDs * 3)
gamma = self.gamma
for idx, idx2 in enumerate(self.c_order):
buf[idx2::3] = [gamma[v] for v in data[idx::3]]
return buf
import random
random.seed(0)
N = 1000
t = Test(N)
data = [random.randint(0, 255) for i in range(3*N)]
r1 = t.do1(data)
r2 = t.do2(data)
print r1 == r2 # check the result
%timeit t.do1(data)
%timeit t.do2(data)
輸出,速度提高了6倍:
True
1000 loops, best of 3: 1.1 ms per loop
10000 loops, best of 3: 176 µs per loop
與流行的看法相反,調用map
函數不會顯着提高速度。 您實際上可能會看到較差的性能。
根據您在這段代碼中花費的時間而定,這可能是一個完美的情況,只需將該循環移植到C即可。 看這里 。
確保您實際上在此for循環中花費了很多時間,否則,調用C代碼的開銷將超過任何潛在的性能提升。
如果您決定使用此代碼將代碼移植到C,請在此處閱讀一些潛在的替代方法:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.